/* ============================================================================
   Tended — the playable demo.

   The app rebuilt in the browser. Every number below is read out of the SwiftUI
   source, not measured off a screenshot:

     TendedTypography  ALL rounded — make() defaults to design: .rounded, body text
                       included. 44 display · 30 title · 22 headline · 18 lead ·
                       16 body · 14 caption · 12 micro. Default weight regular.
     TendedSpacing     screenPadding 16 · tileGap 10 · buttonHeight 56
     JobCard           aspect 120/90 · padding 20 · watermark 100 @ .2 offset +34
                       title headlineRegular = 22 regular (never bold, on either face)
     CardShadow        corner 22 · rest −3° (wide −2°) · swing 3° · .1 · #1B1C16 · top-right
     TilePress         .96 → 1.03 → rest over 620ms
     CategoryProgressBar  height 122 · corner 22 · padding 16 · fill clamped .1–.9
     MonthOverview     3×3 brick: three wide, three narrow, gaps 8 × 10
     CalendarDayCell   cell 48 · circle 36 · number 18 · dot row 9
     CategoryDots      dot 6 · white halo 1.5 · overlap −4 · first on top
     CalendarTaskRow   rounded LEFT only (100), flat right · pad 12 · badge 32 ring 2
                       hard shadow offset +5,+5 at .1
     MarkDonePopup     corner 26 · maxWidth 360 · shadow .18 / 24 / y8

   Laid out at 390×844 device points and scaled with one transform, so proportions
   cannot drift per breakpoint — only the scale changes.
   ============================================================================ */

.tdemo,
.tdemo * { box-sizing: border-box; margin: 0; padding: 0; }

.tdemo {
  /* One family for the whole phone. The app has no second typeface. */
  --td-font: ui-rounded, "SF Pro Rounded", -apple-system-round, -apple-system,
             BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif;
  --td-surface: #FFFFFF;
  --td-inset: #F7F6F2;
  --td-ink: #1C1C1E;
  --td-ink-muted: #8E8B85;
  --td-outline: #E2DDD7;
  --td-headers: #444444;
  --td-blue: #2F80FF;
  --td-blue-fill: #D9ECFF;
  --td-shadow: 27, 28, 22;

  --td-w: 390;
  --td-h: 844;
  --tds: 1;
  /* Both scale with the screen. A fixed-width bezel around a shrinking screen stops
     being a phone and becomes a black slab with a stamp in the middle. */
  --td-bezel: calc(12px * var(--tds));
  --td-corner: 52px;              /* screen corner, in unscaled screen space */

  position: relative;
  width: calc(var(--td-w) * 1px * var(--tds) + var(--td-bezel) * 2);
  height: calc(var(--td-h) * 1px * var(--tds) + var(--td-bezel) * 2);
  flex: none;
}

.tdemo-phone {
  position: absolute; inset: 0;
  /* The screen's radius scales with everything else, so the bezel's outer radius is that
     plus its own thickness. Dividing by the scale instead — which is what this used to do
     — made the white screen and the black frame disagree at every corner. */
  border-radius: calc(var(--td-corner) * var(--tds) + var(--td-bezel));
  background: #1c1c1e;
  padding: var(--td-bezel);
  box-shadow:
    0 2px 0 rgba(255, 255, 255, .12) inset,
    0 30px 60px -20px rgba(var(--td-shadow), .45),
    0 8px 20px -8px rgba(var(--td-shadow), .25);
}

/* The hero phone is a poster that opens the real thing — say so with the cursor, and
   lift it a touch on hover so it reads as one object you can press. */
.tdemo.is-poster { cursor: pointer; transition: transform .2s var(--ease-settle, ease); }
.tdemo.is-poster:hover { transform: translateY(-3px); }
.tdemo.is-poster:focus-visible { outline: 3px solid var(--accent-intense, #F97316); outline-offset: 6px; border-radius: 12px; }
.tdemo.is-poster .tdemo-screen { pointer-events: none; }

.tdemo.is-bare { --td-bezel: 0px; --td-corner: 0px; }
.tdemo.is-bare .tdemo-phone { background: none; box-shadow: none; }

.tdemo-screen {
  position: relative;
  width: calc(var(--td-w) * 1px);
  height: calc(var(--td-h) * 1px);
  transform: scale(var(--tds));
  transform-origin: top left;
  border-radius: var(--td-corner);
  overflow: hidden;
  background: var(--td-surface);
  font-family: var(--td-font);
  color: var(--td-ink);
  -webkit-font-smoothing: antialiased;
}

/* status bar */
.td-status {
  position: absolute; top: 0; left: 0; right: 0; height: 54px; z-index: 5;
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: 15px 30px 0;
  font: 600 15px/1 var(--td-font); color: var(--td-ink);
}
.td-status-notch {
  position: absolute; top: 11px; left: 50%; transform: translateX(-50%);
  width: 124px; height: 33px; border-radius: 20px; background: #000;
}
.td-status-right { display: flex; gap: 5px; align-items: center; }
.td-status-right i {
  display: block; width: 18px; height: 11px; border-radius: 3px;
  border: 1.3px solid currentColor; padding: 1.5px;
}
.td-status-right i::after {
  content: ''; display: block; width: 75%; height: 100%;
  background: currentColor; border-radius: 1px;
}

/* ── scroll body ────────────────────────────────────────────────────────── */

.td-app {
  position: absolute; inset: 54px 0 0;
  overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0 16px 44px;
}
.td-app::-webkit-scrollbar { display: none; }

/* ── day bar ────────────────────────────────────────────────────────────── */

.td-daybar { display: flex; align-items: center; gap: 8px; padding: 10px 0 0; }
.td-daybar-title { flex: 1; text-align: center; min-width: 0; }

.td-daybar h2 {
  font: 700 30px/1.15 var(--td-font);           /* screenTitle */
  letter-spacing: -.4px; color: var(--td-headers);
}
.td-daybar p {
  margin-top: 2px;
  font: 400 18px/1.3 var(--td-font);            /* lead */
  color: var(--td-ink-muted);
}

.td-navbtn {
  flex: none; width: 32px; height: 32px; padding: 0;
  border: 0; background: none; cursor: pointer;
  color: var(--td-outline); transition: color .15s;
}
.td-navbtn:hover:not(:disabled) { color: var(--td-ink-muted); }
.td-navbtn:disabled { opacity: .35; cursor: default; }
.td-navbtn svg { width: 100%; height: 100%; display: block; }

/* ── job grid ───────────────────────────────────────────────────────────── */

.td-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 16px; }

.td-card {
  position: relative; aspect-ratio: 120 / 90; min-height: 96px;
  border: 0; background: none; padding: 0; display: block; width: 100%;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}

.td-card-shadow {
  position: absolute; inset: 0; border-radius: 22px;
  background: rgba(var(--td-shadow), .1);
  transform-origin: top right; transform: rotate(-3deg);
}

.td-card-face {
  position: absolute; inset: 0; border-radius: 22px;
  padding: 20px; overflow: hidden;
  display: flex; align-items: flex-start;
  background: var(--cat-main); text-align: left;
}

.td-card-wm {
  position: absolute; right: -34px; bottom: -34px;
  width: 100px; height: 100px; opacity: .2; color: #fff;
}

.td-card-title {
  position: relative;
  /* JobCard uses headlineRegular — 22, REGULAR weight, and the same font on both faces.
     The strikethrough and the fade are what say "done"; the weight never changes. */
  font: 400 22px/1.18 var(--td-font);
  letter-spacing: -.2px; color: var(--cat-text);
}

.td-card.is-done .td-card-face { background: var(--cat-faded); opacity: .8; }
.td-card.is-done .td-card-title { text-decoration: line-through; text-decoration-thickness: 1.5px; }

.td-card-badge {
  position: absolute; top: 14px; right: 14px; width: 22px; height: 22px;
  color: var(--cat-text); opacity: .55;
}
.td-card:not(.is-late) .td-card-badge { display: none; }

.td-card.is-pulsing .td-card-face { animation: td-pulse-face 620ms cubic-bezier(.25,.9,.3,1); }
.td-card.is-pulsing .td-card-shadow { animation: td-pulse-shadow 620ms cubic-bezier(.25,.9,.3,1); }

@keyframes td-pulse-face {
  0% { transform: scale(1); } 19% { transform: scale(.96); }
  48% { transform: scale(1.03); } 100% { transform: scale(1); }
}
@keyframes td-pulse-shadow {
  0% { transform: rotate(-3deg); } 19% { transform: rotate(0deg); }
  48% { transform: rotate(-6deg); } 100% { transform: rotate(-3deg); }
}
@media (prefers-reduced-motion: reduce) {
  .td-card.is-pulsing .td-card-face,
  .td-card.is-pulsing .td-card-shadow,
  .td-cat.is-pulsing .td-cat-face,
  .td-cat.is-pulsing .td-cat-shadow,
  .td-row.is-pulsing { animation: none; }
}

.td-add {
  aspect-ratio: 120 / 90; min-height: 96px;
  border: 2px dashed var(--td-outline); border-radius: 22px; background: var(--td-inset);
  display: grid; place-items: center; color: var(--td-outline);
}
.td-add svg { width: 34px; height: 34px; }

.td-empty {
  margin-top: 24px; display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.td-empty img { width: 150px; height: auto; }
.td-empty p {
  font: 400 18px/1.4 var(--td-font); color: var(--td-ink-muted);
  text-align: center; max-width: 22em;
}

/* ── this month ─────────────────────────────────────────────────────────── */

/* Its own block under the day, not a continuation of it. */
.td-month { margin-top: 44px; }

.td-month-head { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.td-month-head h3 {
  flex: 1; text-align: center;
  font: 700 30px/1.15 var(--td-font); letter-spacing: -.4px;
  color: var(--td-ink);                    /* MonthNavHeader uses ink, not headers */
}

/* three wide + three narrow, bricked so two wide never stack in the same columns */
.td-bricks { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px 8px; }

.td-cat {
  position: relative; height: 122px;
  border: 0; background: none; padding: 0; width: 100%;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.td-cat.is-wide { grid-column: span 2; }

/* Same skew shadow as the job tiles — CategoryProgressBar casts one too. Wide tiles rest
   at −2° rather than −3°: the same angle across a longer card drops the far corner much
   further and the shadow starts to read as a second tile. */
.td-cat-shadow {
  position: absolute; inset: 0; border-radius: 22px;
  background: rgba(var(--td-shadow), .1);
  transform-origin: top right; transform: rotate(-3deg);
}
.td-cat.is-wide .td-cat-shadow { transform: rotate(-2deg); }

/* Same live tap as the job tiles — CategoryProgressBar wraps PressableTile too and runs
   the identical squish. Only the shadow differs: it swings flat, then out past its own
   rest by `shadowSwing` (3°), so a wide tile pops to −5 where a narrow one pops to −6. */
.td-cat.is-pulsing .td-cat-face { animation: td-pulse-face 620ms cubic-bezier(.25,.9,.3,1); }
.td-cat.is-pulsing .td-cat-shadow { animation: td-pulse-shadow 620ms cubic-bezier(.25,.9,.3,1); }
.td-cat.is-wide.is-pulsing .td-cat-shadow { animation-name: td-pulse-shadow-wide; }

@keyframes td-pulse-shadow-wide {
  0% { transform: rotate(-2deg); } 19% { transform: rotate(0deg); }
  48% { transform: rotate(-5deg); } 100% { transform: rotate(-2deg); }
}

.td-cat-face {
  position: absolute; inset: 0; padding: 16px;
  border-radius: 22px; overflow: hidden;
  display: flex; flex-direction: column; justify-content: space-between;
  text-align: left; background: var(--cat-faded);
}
.td-cat.is-empty .td-cat-face { background: var(--td-inset); }

/* The fill IS the bar: a flat main-coloured band over the faded track, shaped only by
   the face's own clip — not a second rounded rectangle laid on top of one. */
.td-cat-fill { position: absolute; inset: 0 auto 0 0; background: var(--cat-main); }
.td-cat-body { position: relative; }

.td-cat h4 {
  font: 400 30px/1.05 var(--td-font);          /* titleTile */
  color: var(--cat-text); letter-spacing: -.4px; white-space: nowrap;
}
.td-cat.is-wide h4 { font-size: 44px; line-height: 1; letter-spacing: -.8px; }  /* displayTile */
.td-cat.is-empty h4 { color: var(--td-headers); }

.td-cat-stats { position: relative; font: 400 18px/1.25 var(--td-font); color: var(--cat-text); }
.td-cat-stats b { font-weight: 700; }
.td-cat.is-empty .td-cat-stats { color: var(--td-ink-muted); }

/* ── calendar ───────────────────────────────────────────────────────────── */

/* MiniCalendar.Metrics: padding 16 · corner 28 · section gap 12 · shadow .08 / 8 / y4.
   It carries its own header (month name + blue chevrons) under the section's nav header —
   both exist in the app, and they say different things. */
.td-cal {
  margin-top: 16px; padding: 16px;
  background: var(--td-surface); border-radius: 28px;
  box-shadow: 0 4px 8px rgba(var(--td-shadow), .08);
}
.td-cal-head { display: flex; align-items: center; justify-content: space-between; padding-bottom: 12px; }
.td-cal-head strong { font: 700 22px/1.1 var(--td-font); color: var(--td-ink); }   /* headlineBold */
.td-cal-nav { display: flex; gap: 4px; }
.td-cal-nav button { border: 0; background: none; cursor: pointer; color: var(--td-blue); width: 18px; height: 18px; padding: 0 10px; box-sizing: content-box; }
.td-cal-nav svg { width: 100%; height: 100%; }
.td-cal-nav button:first-child svg { transform: rotate(180deg); }

.td-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); margin: 0 -6px; }
.td-cal-dow {
  text-align: center; padding-bottom: 6px;
  font: 600 12px/1 var(--td-font); letter-spacing: .5px;
  color: var(--td-ink-muted); text-transform: uppercase;
}

.td-day {
  position: relative; height: 48px;                  /* Metrics.cellHeight */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px;                                          /* numberDotGap */
  border: 0; background: none; padding: 0; cursor: default;
}
.td-day.is-selectable { cursor: pointer; }
.td-day.is-blank { visibility: hidden; }

.td-day-num {
  width: 36px; height: 36px; border-radius: 50%;     /* Metrics.circle */
  display: grid; place-items: center;
  font: 400 18px/1 var(--td-font);                   /* TendedTypography.lead */
  color: var(--td-ink);
}
.td-day.is-today .td-day-num { color: var(--td-blue); }
.td-day.is-past .td-day-num { color: var(--td-ink-muted); opacity: .45; }
.td-day.is-picked .td-day-num { background: var(--td-blue-fill); color: var(--td-blue); }
/* the task panel's own calendar fills every occurrence in the category's faded shade */
.td-day.is-occ .td-day-num { background: var(--cat-faded); color: var(--cat-text); }

/* dots: 6px of colour inside a 1.5px white halo, overlapping by 4, first one on top */
.td-day-dots { display: flex; height: 9px; }
.td-day-dots i {
  display: block; width: 9px; height: 9px; border-radius: 50%;
  background: var(--td-surface); position: relative;
}
.td-day-dots i + i { margin-left: -4px; }
.td-day-dots i::after {
  content: ''; position: absolute; inset: 1.5px; border-radius: 50%; background: var(--dot);
}

/* expanded day rows */
.td-day-rows {
  grid-column: 1 / -1;
  padding: 6px 0 12px 6px; margin-right: -6px;      /* the pills run off the right edge */
  display: flex; flex-direction: column; gap: 10px;
}

.td-row {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  padding: 12px; width: 100%; border: 0; cursor: pointer; text-align: left;
  border-radius: 100px 0 0 100px;                   /* rounded left, flat right */
  background: var(--cat-main);
  font: 400 16px/1.25 var(--td-font); color: var(--cat-text);
  box-shadow: 5px 5px 0 rgba(var(--td-shadow), .1); /* hard, no blur */
}
.td-row.is-done { background: var(--cat-faded); }
.td-row.is-done .td-row-name { text-decoration: line-through; }
.td-row-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.td-row-badge {
  flex: none; width: 32px; height: 32px; border-radius: 50%;
  border: 2px solid #fff; display: grid; place-items: center;
}
.td-row-badge svg { width: 16px; height: 16px; color: #fff; }
/* a tug to the right rather than a squish — reads better on a wide pill */
.td-row.is-pulsing { animation: td-tug 640ms cubic-bezier(.25,.9,.3,1); }
@keyframes td-tug { 0% { transform: none; } 22% { transform: translateX(10px); } 100% { transform: none; } }

/* ── mark-done popup ────────────────────────────────────────────────────── */

.td-scrim {
  /* Above the task sheet (50), because the sheet's own calendar opens this popup — a
     mark-done dialog rendered underneath the thing that launched it is invisible. */
  position: absolute; inset: 0; z-index: 60;
  background: rgba(var(--td-shadow), .32);
  display: grid; place-items: center; padding: 16px;
  opacity: 0; pointer-events: none; transition: opacity .22s;
}
.td-scrim.is-on { opacity: 1; pointer-events: auto; }

.td-popup {
  position: relative; width: 100%; max-width: 360px;
  background: var(--td-surface); border-radius: 26px; padding: 32px;
  box-shadow: 0 8px 24px rgba(var(--td-shadow), .18);
  transform: scale(.94); transition: transform .22s cubic-bezier(.25,.9,.3,1);
}
.td-scrim.is-on .td-popup { transform: scale(1); }

.td-popup h3 {
  font: 700 30px/1.12 var(--td-font); letter-spacing: -.4px;
  color: var(--td-headers); padding-right: 28px;
}
.td-popup-sched { margin-top: 16px; }
.td-popup-sched b { display: block; font: 400 16px/1.35 var(--td-font); color: var(--td-ink); }
.td-popup-sched span { display: block; margin-top: 4px; font: 400 16px/1.35 var(--td-font); color: var(--td-ink-muted); }

.td-cta {
  margin-top: 20px; width: 100%; height: 56px;
  border: 0; border-radius: 28px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--cat-intense); color: #fff;
  font: 600 19px/1 var(--td-font);
}
.td-cta svg { width: 24px; height: 24px; }

.td-secondary {
  margin-top: 4px; width: 100%; height: 56px;
  border: 0; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  color: var(--td-ink-muted); font: 600 18px/1 var(--td-font);
}
.td-secondary svg { width: 21px; height: 21px; }

.td-x {
  position: absolute; top: 16px; right: 16px;
  width: 30px; height: 30px; border: 0; cursor: pointer; padding: 7px;
  border-radius: 50%; background: var(--td-inset); color: var(--td-ink-muted);
}
.td-x svg { width: 100%; height: 100%; display: block; }

/* ── task detail sheet ──────────────────────────────────────────────────── */

.td-sheet-wrap {
  position: absolute; inset: 0; z-index: 50;
  background: rgba(var(--td-shadow), .28);
  opacity: 0; pointer-events: none; transition: opacity .28s;
}
.td-sheet-wrap.is-on { opacity: 1; pointer-events: auto; }

.td-sheet {
  position: absolute; left: 0; right: 0; bottom: 0; top: 44px;
  background: var(--td-surface); border-radius: 26px 26px 0 0;
  overflow-y: auto; scrollbar-width: none; padding: 0 16px 40px;
  transform: translateY(100%); transition: transform .32s cubic-bezier(.25,.9,.3,1);
}
.td-sheet::-webkit-scrollbar { display: none; }
.td-sheet-wrap.is-on .td-sheet { transform: translateY(0); }

.td-handle { width: 36px; height: 4px; border-radius: 2px; background: var(--cat-faded); margin: 10px auto 0; }

.td-sheet h3 {
  margin-top: 22px; font: 700 30px/1.12 var(--td-font);
  letter-spacing: -.4px; color: var(--td-headers); padding-right: 36px;
}
.td-lede { margin-top: 32px; font: 400 18px/1.45 var(--td-font); color: var(--td-headers); }

.td-links { margin-top: 32px; display: flex; flex-direction: column; gap: 8px; }
.td-links a { font: 400 16px/1.4 var(--td-font); color: var(--td-blue); text-decoration: underline; text-underline-offset: 2px; }
.td-links a::before { content: '•'; margin-right: 8px; color: var(--td-ink-muted); }

.td-hair { height: 1px; background: var(--td-outline); margin: 24px 0; }

.td-schedrow { display: flex; align-items: center; gap: 12px; }
.td-schedrow dt { font: 600 18px/1.2 var(--td-font); color: var(--td-ink); }
.td-schedrow dd { flex: 1; text-align: right; font: 400 18px/1.2 var(--td-font); color: var(--td-ink-muted); }
.td-schedrow svg { width: 18px; height: 18px; color: var(--td-outline); flex: none; }

.td-sheet .td-cal { box-shadow: none; padding-left: 0; padding-right: 0; }

/* ── open / close chrome (outside the phone) ────────────────────────────── */

.tdemo-stage {
  position: fixed; inset: 0; z-index: 900;
  display: none; place-items: center; padding: 24px;
  background: rgba(27, 28, 22, .62);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  opacity: 0; transition: opacity .3s;
}
.tdemo-stage.is-mounted { display: grid; }
.tdemo-stage.is-on { opacity: 1; }

/* The hint bar is fixed to the window, not the stage, so the centring box has to end
   above it — matches `reserve` in demo.js. */
@media (min-width: 768px) { .tdemo-stage { padding-bottom: 96px; } }

/* Fullscreen on a phone means fullscreen: the stage's own gutter goes too. */
.tdemo-stage.is-bare-stage { padding: 0; }

.tdemo-exit {
  position: fixed; top: 20px; right: 20px; z-index: 910;
  width: 44px; height: 44px; padding: 11px; border: 0; cursor: pointer;
  border-radius: 50%; background: rgba(255, 255, 255, .92); color: #1C1C1E;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .25);
}
.tdemo-exit svg { width: 100%; height: 100%; display: block; }

.tdemo-hint {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  z-index: 910; color: rgba(255, 255, 255, .8);
  font: 500 14px/1 -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  background: rgba(0, 0, 0, .3); padding: 9px 16px; border-radius: 999px;
}
@media (max-width: 767px) { .tdemo-hint { display: none; } }

body.tdemo-locked { overflow: hidden; }
