/* ============================================================================
   Speak of the Bevill — life dashboard
   ----------------------------------------------------------------------------
   A light, Apple-flavoured system: warm off-white ground, a soft out-of-focus
   colour wash for the glass to have something to refract, and translucent
   cards over the top. One typeface (the platform's own), hierarchy carried by
   weight, size and tracking rather than a second family — so nothing has to be
   downloaded before the page can paint.

   ========================================================================== */

:root {
  /* Ground — warm, never pure white, never on the grey axis */
  --ground:      #f4f2ef;
  --paper:       #fbfaf8;

  /* Ink */
  --ink:         #1c1b19;
  --ink-2:       #45423e;
  --ink-3:       #6f6b65;
  --ink-4:       #9b968e;

  /* Glass — what the cards are made of */
  --glass:       rgba(255, 255, 255, 0.68);
  --glass-2:     rgba(255, 255, 255, 0.78);
  --glass-line:  rgba(255, 255, 255, 0.85);
  --hairline:    rgba(28, 27, 25, 0.10);
  --hairline-2:  rgba(28, 27, 25, 0.055);
  --well:        rgba(28, 27, 25, 0.045);

  /* Accent + semantics, used sparingly */
  --accent:      #0071e3;
  --accent-deep: #0059b3;
  --accent-wash: rgba(0, 113, 227, 0.10);
  --good:        #2f9e5f;
  --warn:        #d98324;
  --alert:       #d9453d;

  /* Elevation: two layers, both soft — Apple shadows are diffuse, not dark */
  --lift-1: 0 1px 2px rgba(28,27,25,.05), 0 6px 18px rgba(28,27,25,.05);
  --lift-2: 0 2px 4px rgba(28,27,25,.06), 0 16px 42px rgba(28,27,25,.09);

  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 26px;

  --ui: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
        "Segoe UI", system-ui, "Helvetica Neue", Arial, sans-serif;
  --ease: cubic-bezier(.22,.61,.36,1);
  --ease-out: cubic-bezier(.16,1,.3,1);

  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  min-height: 100vh;
  font-family: var(--ui);
  color: var(--ink);
  background: var(--ground);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
a { color: inherit; }
button { font: inherit; color: inherit; }

/* ---- The colour wash the glass refracts -------------------------------- */
/* Deliberately desaturated and very large: it should read as light in the
   room, not as a gradient anyone notices. */
.blobs { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }
.blob { position: absolute; border-radius: 50%; filter: blur(110px); opacity: .34; }
.blob.b1 { width: 62vw; height: 62vw; min-width: 560px; min-height: 560px;
  background: #cadcef; top: -22vw; left: -14vw; animation: drift1 34s ease-in-out infinite; }
.blob.b2 { width: 50vw; height: 50vw; min-width: 440px; min-height: 440px;
  background: #f2e2d2; top: 6vh; right: -16vw; animation: drift2 41s ease-in-out infinite; }
.blob.b3 { width: 46vw; height: 46vw; min-width: 420px; min-height: 420px;
  background: #d8e7de; bottom: -20vw; left: 30vw; animation: drift3 47s ease-in-out infinite; }
@keyframes drift1 { 0%,100%{transform:translate(0,0) scale(1)} 50%{transform:translate(5vw,3vh) scale(1.08)} }
@keyframes drift2 { 0%,100%{transform:translate(0,0) scale(1)} 50%{transform:translate(-4vw,5vh) scale(1.06)} }
@keyframes drift3 { 0%,100%{transform:translate(0,0) scale(1)} 50%{transform:translate(3vw,-4vh) scale(1.09)} }
@media (prefers-reduced-motion: reduce) { .blob { animation: none !important; } }

/* ---- Nav ---------------------------------------------------------------- */
nav {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 12px 28px;
  background: rgba(251, 250, 248, .72);
  backdrop-filter: saturate(180%) blur(24px);
  -webkit-backdrop-filter: saturate(180%) blur(24px);
  border-bottom: 1px solid var(--hairline-2);
}
.nav-left { display: flex; align-items: center; gap: 6px; min-width: 0; }
.brand { display: inline-flex; align-items: center; text-decoration: none; }
/* The mark carries its own corner radius, so don't round it twice. */
.brand img { height: 30px; width: auto; display: block; }

.nav-links { display: flex; align-items: center; gap: 2px; margin-left: 14px; }
.nav-links a {
  font-size: 14px; font-weight: 500; letter-spacing: -.01em; text-decoration: none;
  color: var(--ink-3); padding: 7px 13px; border-radius: 999px;
  transition: color .18s var(--ease), background .18s var(--ease);
}
.nav-links a:hover { color: var(--ink); background: var(--well); }
.nav-links a[aria-current="page"] { color: var(--ink); background: rgba(255,255,255,.9); box-shadow: var(--lift-1); }

.nav-right { display: flex; align-items: center; gap: 14px; }

/* ---- Top-right status: date, time, weather ------------------------------ */
.status {
  display: flex; align-items: center; gap: 0;
  padding: 5px 6px; border-radius: 999px;
  background: rgba(255,255,255,.7); border: 1px solid var(--hairline-2);
  backdrop-filter: saturate(180%) blur(20px); -webkit-backdrop-filter: saturate(180%) blur(20px);
  box-shadow: var(--lift-1);
}
.status-cell { display: flex; flex-direction: column; padding: 3px 14px; line-height: 1.15; }
/* Divider between any two cells, including the weather block. */
.status > * + * { border-left: 1px solid var(--hairline-2); }
.status-cell b { font-size: 15px; font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.status-cell span { font-size: 10.5px; font-weight: 500; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-4); }
.status-wx { display: flex; align-items: center; gap: 9px; padding-right: 6px; }
.status-wx .wx-glyph { font-size: 21px; line-height: 1; }
#status-weather { cursor: pointer; border-radius: 999px; transition: background .18s var(--ease); }
#status-weather:hover { background: var(--well); }
@media (max-width: 1000px) { .status-cell.status-date { display: none; } }
/* Too little room for brand + links + status on one line, but the date, time
   and weather are the point of the cluster — so wrap it onto its own row
   rather than dropping it. */
@media (max-width: 720px) {
  nav { flex-wrap: wrap; gap: 10px 12px; }
  .nav-right { order: 3; width: 100%; justify-content: stretch; gap: 8px; }
  .status { flex: 1; min-width: 0; justify-content: space-around; }
  .status-cell.status-date { display: flex; }
  .status-cell { padding: 3px 9px; }
}

/* ---- Layout ------------------------------------------------------------- */
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 28px 88px; }
.wrap.wide { max-width: 1360px; }

.page-head { padding: 40px 0 6px; }
.page-title { margin: 0; font-size: clamp(30px, 4vw, 40px); font-weight: 700; letter-spacing: -.035em; line-height: 1.08; }
.page-sub { margin: 9px 0 0; font-size: 15.5px; line-height: 1.5; color: var(--ink-3); }

.dash-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 20px; margin-top: 26px;
  --card-h: 460px; }
.dash-grid > * { min-width: 0; }

/* Every card is the same height, so a long list can't drag its whole row taller
   than the rest of the board. Content that outgrows the card scrolls inside it. */
.dash-grid > .panel { height: var(--card-h); }
.panel-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: var(--hairline) transparent; }
.panel-scroll::-webkit-scrollbar { width: 7px; }
.panel-scroll::-webkit-scrollbar-thumb { background: var(--hairline); border-radius: 99px; }
.panel-scroll::-webkit-scrollbar-track { background: transparent; }
/* Fade the cut edge so a scrolled list doesn't end mid-row on a hard line. */
.panel-scroll { mask-image: linear-gradient(180deg, #000 calc(100% - 18px), transparent 100%); }
.panel-scroll:not(.is-scrollable) { mask-image: none; }

@media (max-width: 720px) {
  .dash-grid > .panel { height: auto; }
  .panel-scroll { overflow: visible; mask-image: none; }
}
.col-4 { grid-column: span 4; } .col-5 { grid-column: span 5; }
.col-6 { grid-column: span 6; } .col-7 { grid-column: span 7; }
.col-8 { grid-column: span 8; } .col-12 { grid-column: span 12; }
@media (max-width: 1080px) { .col-4, .col-5, .col-6, .col-7 { grid-column: span 6; } .col-8 { grid-column: span 12; } }
@media (max-width: 720px)  { .dash-grid > * { grid-column: span 12 !important; } .dash-grid { gap: 16px; } }

/* ---- The glass card ----------------------------------------------------- */
.panel {
  position: relative; display: flex; flex-direction: column;
  padding: 20px 22px 22px; border-radius: var(--r-xl);
  background: var(--glass);
  border: 1px solid var(--glass-line);
  backdrop-filter: saturate(180%) blur(30px);
  -webkit-backdrop-filter: saturate(180%) blur(30px);
  box-shadow: var(--lift-1);
  transition: box-shadow .3s var(--ease), transform .3s var(--ease);
}
.panel:hover { box-shadow: var(--lift-2); }

.panel-head { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.panel-head h3 {
  margin: 0; font-size: 13px; font-weight: 600; letter-spacing: -.005em; color: var(--ink-3);
}
.panel-head .spacer { flex: 1; }
.panel-act {
  font-size: 12.5px; font-weight: 500; cursor: pointer; text-decoration: none;
  padding: 5px 11px; border-radius: 999px; color: var(--ink-2);
  background: transparent; border: 1px solid var(--hairline);
  transition: color .18s var(--ease), background .18s var(--ease), border-color .18s var(--ease);
}
.panel-act:hover { color: var(--accent); border-color: transparent; background: var(--accent-wash); }

/* ---- Buttons ------------------------------------------------------------ */
.btn-primary, .btn-quiet, .pj-btn, .ghost-btn, .auth-submit, .signout-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font-size: 14px; font-weight: 500; letter-spacing: -.01em; cursor: pointer;
  padding: 9px 18px; border-radius: 999px; text-decoration: none; border: 1px solid transparent;
  transition: background .18s var(--ease), border-color .18s var(--ease),
              color .18s var(--ease), transform .1s var(--ease);
}
.btn-primary, .pj-btn, .auth-submit { background: var(--accent); color: #fff; }
.btn-primary:hover, .pj-btn:hover, .auth-submit:hover { background: var(--accent-deep); }
.btn-quiet, .ghost-btn, .signout-btn {
  background: rgba(255,255,255,.72); color: var(--ink); border-color: var(--hairline);
}
.btn-quiet:hover, .ghost-btn:hover, .signout-btn:hover { background: #fff; border-color: var(--ink-4); }
.btn-primary:active, .btn-quiet:active, .pj-btn:active, .ghost-btn:active { transform: scale(.975); }
.ghost-btn.danger { color: var(--alert); border-color: rgba(217,69,61,.28); background: rgba(217,69,61,.06); }
.ghost-btn.danger:hover { background: var(--alert); color: #fff; border-color: var(--alert); }
.pj-btn.added, .pj-btn.disabled { background: var(--well); color: var(--ink-4); cursor: default; }
.ghost-btn, .signout-btn, .panel-act { font-size: 13px; padding: 8px 14px; }

/* Icon-only actions need a square target and a glyph big enough to read as
   what it is — a 13px emoji in a pill sized for words reads as a smudge. */
.panel-act.icon-btn { width: 32px; height: 32px; padding: 0; border-radius: 50%;
  display: inline-grid; place-items: center; flex: none; }
.panel-act.icon-btn svg { width: 17px; height: 17px; display: block; }
.panel-act.icon-btn:hover svg { transform: rotate(35deg); }
.panel-act.icon-btn svg { transition: transform .35s var(--ease); }
@media (prefers-reduced-motion: reduce) { .panel-act.icon-btn:hover svg { transform: none; } }

/* ---- Inputs ------------------------------------------------------------- */
input[type="text"], input[type="email"], input[type="password"], input[type="number"], input[type="date"] {
  font: inherit; font-size: 14.5px; color: var(--ink);
  background: rgba(255,255,255,.8); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 10px 13px; outline: none;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
/* Grid/flex items default to min-width:auto, and an input's intrinsic width is
   ~20 characters — which is what pushed the weight fields past the card edge.
   Inputs must always be free to shrink to their track. */
input, .slug-field, .hl-fields label, .edit-body label { min-width: 0; }
input { max-width: 100%; }
input::placeholder { color: var(--ink-4); }
input:focus { border-color: var(--accent); box-shadow: 0 0 0 3.5px var(--accent-wash); }

/* ---- Pills, tags, chips ------------------------------------------------- */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .01em;
  padding: 4px 10px; border-radius: 999px;
  background: var(--well); color: var(--ink-3); border: 1px solid transparent;
}
.pill .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pill.good  { color: var(--good);  background: rgba(47,158,95,.11); }
.pill.warn  { color: var(--warn);  background: rgba(217,131,36,.12); }
.pill.alert { color: var(--alert); background: rgba(217,69,61,.10); }
.pill.accent{ color: var(--accent);background: var(--accent-wash); }

/* ---- Empty / setup states ---------------------------------------------- */
.empty { padding: 22px 4px; text-align: center; color: var(--ink-4); font-size: 13.5px; line-height: 1.6; }
.empty b { display: block; color: var(--ink-2); font-size: 14.5px; font-weight: 600; margin-bottom: 5px; }
.setup { display: flex; flex-direction: column; gap: 10px; }
.setup p { margin: 0; font-size: 13.5px; line-height: 1.6; color: var(--ink-3); }
.setup code { background: var(--well); padding: 2px 6px; border-radius: 6px; font-size: 12.5px; }

/* ---- Skeleton ----------------------------------------------------------- */
.sk { border-radius: var(--r-sm); background:
  linear-gradient(90deg, rgba(28,27,25,.05) 25%, rgba(28,27,25,.09) 37%, rgba(28,27,25,.05) 63%);
  background-size: 400% 100%; animation: shimmer 1.5s ease infinite; }
@keyframes shimmer { from { background-position: 100% 50%; } to { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) { .sk { animation: none; } }

/* ---- Footer ------------------------------------------------------------- */
footer {
  border-top: 1px solid var(--hairline-2); margin-top: 30px; padding: 22px 28px;
  display: flex; flex-wrap: wrap; gap: 16px; align-items: center; justify-content: space-between;
  color: var(--ink-4); font-size: 12.5px;
}
footer .brand-text { font-weight: 600; color: var(--ink-3); font-size: 13px; }

@media (max-width: 640px) {
  nav { padding: 10px 16px; }
  .wrap { padding-left: 16px; padding-right: 16px; }
  footer { padding-left: 16px; padding-right: 16px; }
}

/* ============================================================================
   HEALTH — weight, total change, and a sparkline of every reading
   ========================================================================== */
.hl-top { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.hl-weight { font-size: 44px; font-weight: 600; letter-spacing: -.045em; line-height: 1; font-variant-numeric: tabular-nums; }
.hl-unit { font-size: 17px; font-weight: 500; color: var(--ink-4); letter-spacing: -.01em; }
.hl-delta { margin-left: auto; }
.hl-meta { margin-top: 8px; font-size: 13px; color: var(--ink-3); }

/* No negative side margin: the card body is a scroll container now, so
   anything hanging outside it gets clipped — it ate the axis labels. */
.hl-chart { position: relative; margin: 18px 0 0; }
.hl-chart svg { display: block; width: 100%; height: 116px; overflow: visible; }
.hl-line { fill: none; stroke: var(--good); stroke-width: 2.25; stroke-linecap: round; stroke-linejoin: round; }
.hl-area { fill: url(#hl-fade); }
.hl-dot { fill: #fff; stroke: var(--good); stroke-width: 2.25; }
.hl-grid { stroke: var(--hairline-2); stroke-width: 1; }
.hl-axis { font-size: 10.5px; fill: var(--ink-4); font-weight: 500; }
.hl-hover { fill: var(--ink); }

.hl-foot { display: flex; align-items: center; gap: 8px; margin-top: 16px; padding-top: 15px; border-top: 1px solid var(--hairline-2); }
.hl-foot input { flex: 1; min-width: 0; }
.hl-range { display: flex; gap: 2px; }
.hl-range button {
  font-size: 12px; font-weight: 500; cursor: pointer; padding: 5px 10px;
  border-radius: 999px; border: 0; background: transparent; color: var(--ink-4);
  transition: background .18s var(--ease), color .18s var(--ease);
}
.hl-range button:hover { color: var(--ink-2); background: var(--well); }
.hl-range button[aria-pressed="true"] { color: var(--ink); background: rgba(255,255,255,.95); box-shadow: var(--lift-1); }

/* ============================================================================
   EVENTS — upcoming, from a Google Calendar secret iCal feed
   ========================================================================== */
.ev-list { display: flex; flex-direction: column; }
.ev-day { display: flex; align-items: baseline; gap: 8px;
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-4); margin: 13px 0 5px; }
.ev-in { font-size: 11px; font-weight: 500; letter-spacing: 0; text-transform: none;
  color: var(--ink-3); background: var(--well); border-radius: 999px; padding: 2px 8px; }
.ev-day:first-child { margin-top: 0; }
.ev {
  display: grid; grid-template-columns: 58px 1fr; gap: 12px; align-items: baseline;
  padding: 7px 10px; margin: 0 -10px; border-radius: var(--r-md); text-decoration: none;
  transition: background .18s var(--ease);
}
.ev:hover { background: rgba(255,255,255,.72); }
.ev-time { font-size: 12.5px; font-weight: 600; color: var(--ink-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ev-time.all-day { color: var(--accent); font-size: 11.5px; }
.ev-body { min-width: 0; }
/* These are spans inside a grid item, so they must be blockified before
   overflow/ellipsis mean anything — inline boxes ignore both. */
.ev-title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: 14.5px; font-weight: 500; letter-spacing: -.01em; line-height: 1.35;
}
.ev-where {
  display: block; font-size: 12.5px; color: var(--ink-4); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ev.is-now { background: var(--accent-wash); }
.ev.is-now .ev-time { color: var(--accent); }

/* ============================================================================
   COUNTDOWN — rotating, from Tracker via Desktopia
   ========================================================================== */
.cd { position: relative; }
.cd-track { position: relative; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; }
.cd-slide { display: none; }
.cd-slide.active {
  display: grid; grid-template-columns: 1fr auto; gap: 18px; align-items: center;
  animation: cdIn .5s var(--ease-out) both;
}
@keyframes cdIn { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }
.cd-inner { min-width: 0; }

/* Full-bleed key art. Two layers cross-fade; the scrim below keeps the type
   legible over whatever the artwork happens to be. */
.cd { overflow: hidden; }
.cd-bg {
  position: absolute; inset: 0; z-index: 0; opacity: 0; pointer-events: none;
  background-size: cover; background-position: center;
  transition: opacity .7s var(--ease); transform: scale(1.04);
  will-change: opacity; backface-visibility: hidden;
}
/* A portrait poster crops hard at this ratio, so let it sit further back. */
.cd-bg.is-poster { background-position: center 22%; filter: saturate(108%); }
/* Darkened at BOTH ends: the header and arrows sit on the top edge, and a
   bright sky up there left them unreadable. The middle stays open so the art
   is still the thing you see. */
/* pointer-events:none is load-bearing, not tidiness: these cover the whole card
   and opacity:0 still hit-tests, so without it they swallow every click on the
   arrows and dots. */
.cd-scrim { position: absolute; inset: 0; z-index: 1; opacity: 0; pointer-events: none;
  transition: opacity .5s var(--ease);
  background: linear-gradient(180deg,
    rgba(12,11,10,.62) 0%, rgba(12,11,10,.26) 24%,
    rgba(12,11,10,.58) 62%, rgba(12,11,10,.90) 100%); }
.cd.has-art .cd-scrim { opacity: 1; }
/* Once art covers the card, the panel's backdrop-filter is filtering something
   nobody can see — and a blur that has to re-rasterise behind two cross-fading
   full-size images is exactly the compositing work Safari struggles with. Drop
   it, and the nested blur on the arrows with it. */
.cd.has-art {
  border-color: rgba(255,255,255,.16); box-shadow: var(--lift-2);
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background: #14130f;
  contain: paint;
}
.cd > .panel-head, .cd > .cd-track, .cd > .cd-nav { position: relative; z-index: 2; }

/* Type inverts over the art. */
.cd.has-art .panel-head h3 { color: rgba(255,255,255,.92); text-shadow: 0 1px 10px rgba(0,0,0,.6); }
.cd.has-art .cd-num, .cd.has-art .cd-title { color: #fff; text-shadow: 0 1px 22px rgba(0,0,0,.5); }
.cd.has-art .cd-lbl, .cd.has-art .cd-when { color: rgba(255,255,255,.82); text-shadow: 0 1px 10px rgba(0,0,0,.55); }
.cd.has-art .cd-out { color: #7ce6a4; }
/* Every control on an art card goes white — the arrows got this treatment and
   the Edit button didn't, leaving dark ink sitting on a photograph. */
.cd.has-art .cd-arrow,
.cd.has-art .panel-act {
  background: rgba(255,255,255,.18); border-color: rgba(255,255,255,.3); color: #fff;
}
.cd.has-art .cd-arrow:hover,
.cd.has-art .panel-act:hover {
  background: rgba(255,255,255,.32); border-color: rgba(255,255,255,.5); color: #fff;
}
.cd.has-art .cd-dots button { background: #fff; opacity: .45; }
.cd.has-art .cd-dots button[aria-current="true"] { background: #fff; opacity: 1; }
.cd.has-art .cd-track { justify-content: flex-end; }
.cd.has-art .cd-slide.active { grid-template-columns: 1fr; }

@media (prefers-reduced-motion: reduce) { .cd-bg { transition: none; } }

.cd-days { display: flex; align-items: baseline; gap: 9px; }
.cd-num { font-size: 52px; font-weight: 650; letter-spacing: -.05em; line-height: .95; font-variant-numeric: tabular-nums; }
.cd-lbl { font-size: 15px; font-weight: 500; color: var(--ink-3); letter-spacing: -.01em; }
.cd-title { margin: 12px 0 4px; font-size: 17px; font-weight: 600; letter-spacing: -.02em; line-height: 1.25; }
.cd-when { font-size: 13px; color: var(--ink-3); }
.cd-out { font-size: 15px; font-weight: 600; color: var(--good); }

.cd-nav { display: flex; align-items: center; gap: 8px; margin-top: 16px; }
.cd-dots { display: flex; gap: 5px; }
.cd-dots button { width: 6px; height: 6px; padding: 0; border: 0; border-radius: 50%;
  background: var(--ink-4); opacity: .35; cursor: pointer; transition: all .25s var(--ease); }
.cd-dots button[aria-current="true"] { opacity: 1; width: 18px; border-radius: 999px; background: var(--ink-3); }
.cd-arrow {
  width: 26px; height: 26px; display: grid; place-items: center; cursor: pointer;
  border-radius: 50%; border: 1px solid var(--hairline); background: rgba(255,255,255,.7);
  color: var(--ink-3); font-size: 13px; line-height: 1;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.cd-arrow:hover { background: #fff; color: var(--ink); }

/* ============================================================================
   NEWS — recent items from Desktopia
   ========================================================================== */
.news-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 4px; }
.news-item {
  display: flex; gap: 12px; padding: 11px 12px; margin: 0 -2px; border-radius: var(--r-md);
  text-decoration: none; color: inherit; transition: background .18s var(--ease);
}
.news-item:hover { background: rgba(255,255,255,.78); }
.news-thumb {
  width: 46px; height: 46px; flex: none; border-radius: var(--r-sm); overflow: hidden;
  background: var(--well); display: grid; place-items: center; font-size: 17px; color: var(--ink-4);
}
.news-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.news-body { min-width: 0; flex: 1; }
.news-title {
  font-size: 13.5px; font-weight: 500; line-height: 1.35; letter-spacing: -.008em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.news-meta { margin-top: 4px; font-size: 11.5px; color: var(--ink-4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.news-feed { color: var(--ink-3); font-weight: 500; }

/* ============================================================================
   PROJECTS PAGE
   ========================================================================== */
header { text-align: center; padding: 38px 0 4px; }
header h1 img { width: min(200px, 48vw); height: auto; display: block; margin: 0 auto; }
.subtitle { color: var(--ink-3); font-size: 16px; line-height: 1.55; margin: 14px auto 0; max-width: 520px; text-align: center; }

.search {
  margin: 30px auto 8px; max-width: 600px; display: flex; align-items: center; gap: 11px;
  padding: 12px 16px; border-radius: 999px;
  background: var(--glass-2); border: 1px solid var(--glass-line);
  backdrop-filter: saturate(180%) blur(24px); -webkit-backdrop-filter: saturate(180%) blur(24px);
  box-shadow: var(--lift-1); transition: box-shadow .2s var(--ease);
}
.search:focus-within { box-shadow: var(--lift-2), 0 0 0 3.5px var(--accent-wash); }
.search svg { width: 17px; height: 17px; color: var(--ink-4); flex: none; }
.search input { flex: 1; border: 0; background: transparent; font-size: 15px; outline: none; padding: 0; }
.search input:focus { box-shadow: none; }
.kbd { font-size: 11.5px; color: var(--ink-4); border: 1px solid var(--hairline); border-radius: 6px; padding: 2px 7px; }

.sec-head { display: flex; align-items: baseline; justify-content: space-between; margin: 44px 0 18px; }
.sec-head h2 { font-size: 20px; font-weight: 650; letter-spacing: -.025em; margin: 0; }
.count { font-size: 13px; color: var(--ink-4); }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 18px; }
.card {
  position: relative; display: flex; flex-direction: column; gap: 13px;
  padding: 20px; min-height: 172px; border-radius: var(--r-xl);
  background: var(--glass); border: 1px solid var(--glass-line);
  backdrop-filter: saturate(180%) blur(30px); -webkit-backdrop-filter: saturate(180%) blur(30px);
  box-shadow: var(--lift-1); text-decoration: none; color: inherit; cursor: pointer;
  transition: transform .28s var(--ease), box-shadow .28s var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: var(--lift-2); }
.icon {
  width: 46px; height: 46px; display: grid; place-items: center; font-size: 23px;
  border-radius: var(--r-md); overflow: hidden; color: #fff;
  background: linear-gradient(160deg, #6fb1f5, var(--accent));
  box-shadow: 0 5px 14px rgba(0,113,227,.26);
}
.icon.has-img { background: #fff; box-shadow: var(--lift-1); }
.icon img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card h3 { margin: 0; font-size: 16.5px; font-weight: 600; letter-spacing: -.02em; }
.card p { margin: 0; color: var(--ink-3); font-size: 13.5px; line-height: 1.5; }
.card .host { margin-top: auto; display: flex; align-items: center; gap: 10px;
  font-size: 12.5px; color: var(--accent); font-weight: 500; }

.card-actions { position: absolute; top: 11px; right: 11px; display: flex; gap: 5px; opacity: 0; transition: opacity .18s var(--ease); }
.card:hover .card-actions, .card:focus-within .card-actions { opacity: 1; }
.card-actions button {
  width: 27px; height: 27px; display: grid; place-items: center; border-radius: 50%;
  background: rgba(255,255,255,.94); border: 1px solid var(--hairline); color: var(--ink-3);
  font-size: 13px; line-height: 1; cursor: pointer; box-shadow: var(--lift-1);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.card-actions button:hover { background: #fff; color: var(--ink); }
.card-actions .rm:hover { background: var(--alert); color: #fff; border-color: var(--alert); }
.card[draggable="true"] { cursor: grab; }
.card.dragging { opacity: .4; cursor: grabbing; }
.card.drag-over { box-shadow: var(--lift-2), 0 0 0 2px var(--accent); }

.add-tile {
  display: grid; place-items: center; gap: 9px; min-height: 172px; border-radius: var(--r-xl);
  border: 1.5px dashed var(--hairline); background: rgba(255,255,255,.28); color: var(--ink-4);
  cursor: pointer; transition: border-color .2s var(--ease), color .2s var(--ease), background .2s var(--ease);
}
.add-tile:hover { border-color: var(--accent); color: var(--accent); background: rgba(255,255,255,.6); }
.add-tile .plus { width: 42px; height: 42px; border-radius: var(--r-md); display: grid; place-items: center;
  font-size: 25px; font-weight: 300; border: 1px solid var(--hairline); background: rgba(255,255,255,.8); }
.add-tile span { font-size: 13.5px; font-weight: 500; }

/* ---- Modals ------------------------------------------------------------- */
.overlay {
  position: fixed; inset: 0; z-index: 100; display: none; align-items: center; justify-content: center;
  padding: 24px; background: rgba(28,27,25,.28);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.overlay.open { display: flex; animation: fade .2s var(--ease) both; }
@keyframes fade { from { opacity: 0 } to { opacity: 1 } }
.modal {
  width: 100%; max-width: 510px; max-height: 84vh; display: flex; flex-direction: column;
  border-radius: var(--r-xl); background: rgba(251,250,248,.94);
  border: 1px solid var(--glass-line);
  backdrop-filter: saturate(180%) blur(40px); -webkit-backdrop-filter: saturate(180%) blur(40px);
  box-shadow: 0 30px 80px rgba(28,27,25,.22); overflow: hidden;
  animation: pop .28s var(--ease-out) both;
}
@keyframes pop { from { opacity: 0; transform: translateY(14px) scale(.985) } to { opacity: 1; transform: none } }
.modal-head { padding: 19px 22px; border-bottom: 1px solid var(--hairline-2); display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.modal-head h3 { margin: 0; font-size: 17px; font-weight: 650; letter-spacing: -.02em; }
.modal-head p { margin: 4px 0 0; font-size: 13px; color: var(--ink-3); line-height: 1.45; }
.modal-close { background: none; border: 0; color: var(--ink-4); font-size: 22px; cursor: pointer; line-height: 1; padding: 0 2px; }
.modal-close:hover { color: var(--ink); }

.proj-list { padding: 10px; overflow-y: auto; }
.proj { display: flex; align-items: center; gap: 13px; padding: 10px 12px; border-radius: var(--r-md); transition: background .15s var(--ease); }
.proj:hover { background: var(--well); }
.proj .pj-icon { width: 38px; height: 38px; border-radius: var(--r-sm); display: grid; place-items: center;
  font-weight: 600; color: #fff; background: linear-gradient(160deg, #6fb1f5, var(--accent)); flex: none; }
.proj .pj-meta { flex: 1; min-width: 0; }
.proj .pj-name { font-size: 14.5px; font-weight: 500; }
.proj .pj-url { font-size: 12px; color: var(--ink-4); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pj-btn { flex: none; font-size: 13px; padding: 7px 15px; }

.url-form { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; padding: 15px; border-bottom: 1px solid var(--hairline-2); }
.url-form #url-name { grid-column: 1; }
.url-form .slug-field { grid-column: 2 / span 2; }
.url-form #url-input { grid-column: 1 / span 2; }
.url-form .pj-btn { grid-column: 3; }

.edit-body { padding: 17px 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 13px; }
.edit-body label { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; font-weight: 500; color: var(--ink-3); }
.icon-editor { display: flex; gap: 13px; align-items: flex-start; padding-top: 3px; }
.icon-preview { width: 56px; height: 56px; flex: none; border-radius: var(--r-md); overflow: hidden; display: grid;
  place-items: center; font-size: 25px; color: #fff; background: linear-gradient(160deg, #6fb1f5, var(--accent)); }
.icon-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.icon-controls { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.icon-btns { display: flex; flex-wrap: wrap; gap: 6px; }
.edit-foot { display: flex; align-items: center; gap: 9px; padding: 15px 20px; border-top: 1px solid var(--hairline-2); }

/* ---- Short-link field --------------------------------------------------- */
.slug-field { display: flex; align-items: center; min-width: 0; background: rgba(255,255,255,.8);
  border: 1px solid var(--hairline); border-radius: var(--r-md); padding: 0 4px 0 12px;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease); }
.slug-field:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3.5px var(--accent-wash); }
.slug-prefix { flex: none; font-size: 13px; color: var(--ink-4); white-space: nowrap; user-select: none; }
.slug-field input { flex: 1; min-width: 0; background: transparent; border: 0; padding: 10px 6px; font-size: 14px; }
.slug-field input:focus { box-shadow: none; }
.slug-copy { flex: none; width: 28px; height: 28px; display: grid; place-items: center; cursor: pointer;
  background: transparent; border: 0; border-radius: 7px; color: var(--ink-4); font-size: 14px; }
.slug-copy:hover { background: var(--well); color: var(--accent); }
.slug-hint { font-size: 12px; color: var(--ink-4); min-height: 1.2em; font-weight: 400; }
.slug-hint.bad { color: var(--alert); }
.slug-chip { display: inline-flex; align-items: center; margin-left: auto; font-size: 11.5px; font-weight: 500;
  padding: 3px 9px; border-radius: 999px; cursor: pointer; background: var(--well); color: var(--ink-4);
  border: 1px solid transparent; transition: color .15s var(--ease), background .15s var(--ease); }
.slug-chip:hover { color: var(--accent); background: var(--accent-wash); }

/* ---- Toast -------------------------------------------------------------- */
.toast {
  position: fixed; bottom: 26px; left: 50%; transform: translateX(-50%) translateY(16px);
  background: rgba(28,27,25,.92); color: #fff; padding: 11px 20px; border-radius: 999px;
  font-size: 13.5px; font-weight: 500; backdrop-filter: blur(20px);
  box-shadow: 0 12px 40px rgba(28,27,25,.3); opacity: 0; pointer-events: none;
  transition: opacity .26s var(--ease), transform .26s var(--ease); z-index: 200;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---- Auth gate ---------------------------------------------------------- */
.auth-block { display: flex; justify-content: center; margin: 60px 0 8px; }
body.authed .auth-block { display: none; }
body:not(.authed) [data-gated], body:not(.authed) #sign-out { display: none; }
.auth-card {
  width: 100%; max-width: 360px; display: flex; flex-direction: column; gap: 12px; padding: 28px;
  border-radius: var(--r-xl); background: var(--glass-2); border: 1px solid var(--glass-line);
  backdrop-filter: saturate(180%) blur(30px); -webkit-backdrop-filter: saturate(180%) blur(30px);
  box-shadow: var(--lift-2);
}
.auth-sub { text-align: center; color: var(--ink-3); margin: 0 0 6px; font-size: 15px; font-weight: 500; }
.auth-error { color: var(--alert); font-size: 13px; min-height: 1.1em; margin: 0; text-align: center; }
.auth-submit { padding: 11px; width: 100%; }
.auth-submit:disabled { opacity: .55; cursor: default; }

@media (max-width: 520px) {
  .url-form { grid-template-columns: 1fr; }
  .url-form #url-name, .url-form .slug-field, .url-form #url-input, .url-form .pj-btn { grid-column: 1; }
}

/* ---- Weight card settings ---------------------------------------------- */
.hl-settings { margin: -4px 0 14px; padding: 14px; border-radius: var(--r-lg);
  background: var(--well); border: 1px solid var(--hairline-2); }
.hl-settings[hidden] { display: none; }
.hl-settings-note { margin: 0 0 12px; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }
.hl-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.hl-fields label { display: flex; flex-direction: column; gap: 5px; font-size: 11.5px; font-weight: 600;
  letter-spacing: .03em; text-transform: uppercase; color: var(--ink-4); }
.hl-fields input, .hl-fields .ghost-btn { width: 100%; min-width: 0; font-size: 14px; padding: 8px 11px; }
.hl-fields .ghost-btn { justify-content: flex-start; }
@media (max-width: 380px) { .hl-fields { grid-template-columns: 1fr; } }
.hl-settings-foot { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.hl-settings-foot .slug-hint { flex: 1; min-height: 0; }
.hl-goal-line { stroke: var(--accent); stroke-width: 1.5; stroke-dasharray: 4 4; opacity: .65; }
.hl-goal-label { font-size: 10.5px; fill: var(--accent); font-weight: 600; }

/* ============================================================================
   TO DO
   ========================================================================== */
.td-add { display: flex; gap: 8px; margin-bottom: 12px; }
.td-add[hidden] { display: none; }
.td-add input { flex: 1; min-width: 0; }

.td-list { display: flex; flex-direction: column; }
.td-item { display: flex; align-items: flex-start; gap: 11px; padding: 8px 10px; margin: 0 -10px;
  border-radius: var(--r-md); transition: background .16s var(--ease); }
.td-item:hover { background: rgba(255,255,255,.7); }

/* A real checkbox, restyled — keeps keyboard and screen-reader behaviour. */
.td-check { flex: none; width: 19px; height: 19px; margin: 1px 0 0; appearance: none; cursor: pointer;
  border: 1.6px solid var(--ink-4); border-radius: 50%; background: transparent;
  display: grid; place-items: center; transition: background .16s var(--ease), border-color .16s var(--ease); }
.td-check:checked { background: var(--good); border-color: var(--good); }
.td-check:checked::after { content: "✓"; color: #fff; font-size: 11px; font-weight: 700; line-height: 1; }
.td-check:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.td-text { flex: 1; min-width: 0; font-size: 14px; line-height: 1.45; word-break: break-word; }
.td-item.done .td-text { color: var(--ink-4); text-decoration: line-through; }
.td-rm { flex: none; width: 24px; height: 24px; display: grid; place-items: center; cursor: pointer;
  border: 0; border-radius: 50%; background: transparent; color: var(--ink-4); font-size: 15px; line-height: 1;
  opacity: 0; transition: opacity .16s var(--ease), background .16s var(--ease), color .16s var(--ease); }
.td-item:hover .td-rm, .td-editing .td-rm { opacity: 1; }
.td-rm:hover { background: rgba(217,69,61,.12); color: var(--alert); }
.td-clear { margin-top: 10px; }

/* ============================================================================
   TIME UNTIL — shares the countdown's art treatment, adds an editor
   ========================================================================== */
.tu-form { position: relative; z-index: 2; margin-bottom: 14px; padding: 14px;
  border-radius: var(--r-lg); background: rgba(255,255,255,.9); border: 1px solid var(--hairline-2); }
.tu-form[hidden] { display: none; }

/* Editing takes the card over: the slide and dots step aside rather than
   competing for a fixed 460px, and the form becomes the single scroll surface
   so a long list doesn't nest one scroller inside another. */
.cd.is-editing > .cd-track, .cd.is-editing > .cd-nav { display: none; }
.cd.is-editing .tu-form { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin-bottom: 0; }
.cd.is-editing .tu-list { max-height: none; overflow: visible; }
.tu-fields { display: grid; grid-template-columns: 1fr auto; gap: 10px; }
.tu-fields label { display: flex; flex-direction: column; gap: 5px; min-width: 0;
  font-size: 11.5px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; color: var(--ink-4); }
.tu-fields input { width: 100%; min-width: 0; font-size: 14px; padding: 8px 11px; }

.tu-art { display: flex; gap: 11px; margin-top: 11px; }
.tu-preview { width: 92px; height: 58px; flex: none; border-radius: var(--r-sm); overflow: hidden;
  background-size: cover; background-position: center; background-color: var(--well);
  display: grid; place-items: center; font-size: 10.5px; color: var(--ink-4); text-align: center; }
.tu-preview.empty-art { border: 1px dashed var(--hairline); }
.tu-art-controls { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.tu-art-controls input { width: 100%; font-size: 13.5px; padding: 7px 10px; }
.tu-form-foot { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.tu-form-foot .slug-hint { flex: 1; min-height: 0; }

.tu-list { margin-top: 12px; border-top: 1px solid var(--hairline-2); padding-top: 8px;
  display: flex; flex-direction: column; max-height: 148px; overflow-y: auto; }
.tu-list:empty { display: none; }
.tu-row { display: flex; align-items: center; gap: 9px; padding: 5px 2px; font-size: 13px; }
.tu-row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tu-row-date { color: var(--ink-4); font-size: 12px; white-space: nowrap; }
.tu-row .td-rm { opacity: 1; }

/* The editor sits over artwork, so it needs its own opaque ground. */
.cd.has-art .tu-form { background: rgba(255,255,255,.96); border-color: transparent; }

/* ============================================================================
   PAPER — the to-do card reads as notepaper rather than glass
   ----------------------------------------------------------------------------
   A warm tint, faint rules and a fine grain. The grain is generated SVG noise
   rather than an image, so it costs one small data URI and stays sharp at any
   density. Both layers are decoration: pointer-events:none, and the card's own
   children sit above them — an invisible overlay that hit-tests will swallow
   clicks on everything beneath it.
   ========================================================================== */
.panel.paper {
  background:
    linear-gradient(180deg, rgba(255,252,244,.82), rgba(253,250,243,.74));
  border-color: rgba(255,255,255,.9);
}
.panel.paper::after { content: ""; position: absolute; inset: 0; z-index: 0;
  pointer-events: none; border-radius: inherit; }

/* Each row carries its own rule, rather than the list painting a 40px band
   pattern behind them: to-do text wraps often at this width, and one wrapped
   row is 77px, which throws every band below it out of step. A border on the
   row itself cannot drift. The blank lines that make it read as a pad come
   from .td-fill, which takes the leftover height below the last item — nothing
   sits there, so its rhythm only has to look right, not align to anything. */
.panel.paper #td-body { display: flex; flex-direction: column; }
.panel.paper .td-item { border-bottom: 1px solid rgba(40, 34, 24, .07); }
.td-fill { flex: 1 1 auto; min-height: 0; }
.panel.paper .td-fill {
  background-image: repeating-linear-gradient(
    180deg, transparent 0 39px, rgba(40, 34, 24, .07) 39px 40px);
}

/* Fine paper grain. */
.panel.paper::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.42'/%3E%3C/svg%3E");
  opacity: .5; mix-blend-mode: multiply;
}
.panel.paper > * { position: relative; z-index: 1; }

/* The rows sit on the ruling, so they need a lighter hover than glass cards. */
.panel.paper .td-item:hover { background: rgba(255,255,255,.55); }

