/* Palette and letterpress idiom borrowed from The Family Forge
   (family-forge.cade-dopp.workers.dev). Fonts are NOT loaded from Google here —
   this app makes no third-party requests — so the same stacks fall back to
   system faces. */
:root{
  --paper:#ece0c6; --paper-2:#e3d5b6; --paper-3:#d8c8a4; --paper-edge:#c9b691;
  --ink:#1b201c; --ink-2:#2c342d; --ink-soft:#4a544a; --ink-faint:#6d766c;
  --rust:#9d3d1a; --rust-bright:#bd5426; --sage:#5d6b54; --ember:#c9782d;

  --label:"Oswald","Helvetica Neue",Arial,sans-serif;
  --body:"Crimson Pro",Georgia,"Times New Roman",serif;
  --display:"Big Shoulders Display","Oswald","Arial Narrow",sans-serif;

  /* Tokens the dark theme overrides. Light values are exactly what was
     hardcoded before, so light mode renders identically. --sh is an rgb
     triplet rather than a colour, so every rgba(var(--sh),a) shadow in the
     file re-tints from one place. */
  --line:#1b201c;
  --card:rgba(255,251,240,.55);
  --card-2:rgba(255,251,240,.75);
  --press:rgba(27,32,28,.05);
  --on-accent:#fdf6e6;
  --sh:27,32,28;

  --radius:3px;
  --rule:1.5px solid var(--line);
  --shadow:4px 4px 0 rgba(var(--sh),.13);
  --shadow-hard:3px 3px 0 rgba(var(--sh),.35);
  color-scheme:light;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  background:var(--paper); color:var(--ink);
  font:17px/1.55 var(--body);
  -webkit-text-size-adjust:100%;
  padding:0 0 env(safe-area-inset-bottom);
}
h1,h2,h3{margin:0; font-family:var(--display); line-height:1.15; letter-spacing:.01em}
a{color:var(--rust); text-underline-offset:2px}

.topbar{
  position:sticky; top:0; z-index:10; background:var(--paper);
  border-bottom:var(--rule);
  padding:calc(env(safe-area-inset-top) + 12px) 16px 0;
}
.topbar h1{font-size:26px; text-transform:uppercase; letter-spacing:.04em}
.tabs{display:flex; gap:2px; margin-top:10px}
.tabs a{
  flex:1; text-align:center; padding:12px 8px; min-height:48px;
  text-decoration:none; color:var(--ink-soft);
  font-family:var(--label); font-size:13px; font-weight:600;
  letter-spacing:.14em; text-transform:uppercase;
  border-bottom:3px solid transparent;
}
.tabs a[aria-current="page"]{color:var(--rust); border-bottom-color:var(--rust)}

main{padding:18px 16px; max-width:720px; margin:0 auto}
.foot{padding:8px 16px 30px; max-width:720px; margin:0 auto}
.foot p{color:var(--ink-faint); font-size:13px; margin:0; font-family:var(--label); letter-spacing:.04em}
.foot p + p{margin-top:6px}
.foot a{color:var(--rust)}

.muted{color:var(--ink-soft)}
.small{font-size:14px}
.stack>*+*{margin-top:14px}

.card{
  background:var(--card); border:var(--rule); border-radius:var(--radius);
  box-shadow:var(--shadow); padding:14px; display:block;
  text-decoration:none; color:inherit;
}
a.card:active{transform:translate(2px,2px); box-shadow:1px 1px 0 rgba(var(--sh),.13)}
.card h3{font-size:20px}
.card .meta{display:flex; flex-wrap:wrap; gap:6px; margin-top:10px}

.pill{
  display:inline-block; font-family:var(--label); font-size:11px; font-weight:600;
  letter-spacing:.12em; text-transform:uppercase;
  padding:4px 9px; border-radius:99px;
  border:1px solid var(--ink-faint); color:var(--ink-soft); background:transparent;
}

.grouphead{
  display:flex; align-items:baseline; justify-content:space-between; gap:8px;
  margin:24px 0 10px; padding-bottom:5px; border-bottom:1px solid var(--paper-edge);
  font-family:var(--label); font-size:12px; font-weight:600;
  letter-spacing:.2em; text-transform:uppercase; color:var(--ink-soft);
}

button,.btn{
  font-family:var(--label); font-size:14px; font-weight:600;
  letter-spacing:.1em; text-transform:uppercase;
  min-height:48px; padding:12px 16px; border-radius:2px;
  border:1.5px solid var(--ink); background:transparent; color:var(--ink);
  box-shadow:3px 3px 0 rgba(var(--sh),.18); cursor:pointer;
  text-align:center; text-decoration:none;
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
}
button:active,.btn:active{transform:translate(2px,2px); box-shadow:1px 1px 0 rgba(var(--sh),.18)}
.btn-primary{background:var(--rust); border-color:var(--rust); color:var(--on-accent); box-shadow:var(--shadow-hard)}
.btn-primary:active{box-shadow:1px 1px 0 rgba(var(--sh),.35)}
.btn-danger{color:var(--rust); border-color:var(--rust)}
.btn-row{display:flex; gap:10px; flex-wrap:wrap}
.btn-row>*{flex:1 1 150px}
.btn-block{display:flex; width:100%}

label{
  display:block; font-family:var(--label); font-size:13px; font-weight:600;
  letter-spacing:.12em; text-transform:uppercase; margin-bottom:5px;
}
.hint{font-family:var(--body); font-size:14px; color:var(--ink-soft); margin:-1px 0 8px; letter-spacing:0; text-transform:none}
input[type=text], input[type=date], input[type=file], textarea{
  width:100%; font:16px/1.5 var(--body); color:var(--ink);
  background:var(--card-2); border:1.5px solid var(--ink-faint);
  border-radius:var(--radius); padding:11px 12px; min-height:48px;
}
textarea{min-height:86px; resize:vertical}
input:focus, textarea:focus{outline:2px solid var(--rust); outline-offset:1px; border-color:var(--ink)}
fieldset{border:0; padding:0; margin:0}

.checkrow{
  display:flex; align-items:center; gap:12px; padding:12px 13px; min-height:52px;
  background:var(--card); border:var(--rule); border-radius:var(--radius);
  box-shadow:var(--shadow); cursor:pointer;
  font-family:var(--label); letter-spacing:.06em; text-transform:none;
}
.checkrow input{width:22px; height:22px; accent-color:var(--rust); flex:none}
.checkrow .who{font-weight:600}
.checkrow .when{margin-left:auto; color:var(--ink-soft); font-size:13px}

/* One row per person: who they are, whether the plan was sent and reviewed,
   and when. Wraps rather than shrinks the tap targets at 390px. */
.signrow{
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px; padding:11px 13px;
  background:var(--card); border:var(--rule); border-radius:var(--radius);
  box-shadow:var(--shadow);
}
.signrow .who{
  flex:1 1 100%; font-family:var(--display); font-size:19px; line-height:1.2;
  display:flex; align-items:baseline; gap:8px;
}
.signrow .role{
  font-family:var(--label); font-size:10px; font-weight:600; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-faint);
}
.signrow .chks{display:flex; gap:8px}
/* The row is a <label> so the whole thing toggles — but it must not inherit
   the global label styling, or every name renders in shouting caps. */
label.signrow{cursor:pointer; text-transform:none; letter-spacing:normal; font-family:var(--body)}
.signrow .chk{
  display:flex; align-items:center; gap:7px; min-height:44px; padding:0 11px;
  border:1.5px solid var(--ink-faint); border-radius:2px; cursor:pointer;
  font-family:var(--label); font-size:12px; font-weight:600;
  letter-spacing:.1em; text-transform:uppercase; margin:0;
}
.signrow .chk input{width:20px; height:20px; accent-color:var(--rust); flex:none; margin:0}
.signrow .when{margin-left:auto; color:var(--ink-soft); font-size:13px; font-family:var(--label)}

/* A quiet way back up the hierarchy, above the page title. */
.backlink{
  display:inline-flex; align-items:center; min-height:44px; margin-bottom:2px;
  font-family:var(--label); font-size:12px; font-weight:600;
  letter-spacing:.12em; text-transform:uppercase; text-decoration:none;
}
.backlink::before{content:"\2190"; margin-right:7px; font-size:15px}

.namerow{display:flex; align-items:flex-end; gap:10px; margin-bottom:14px}

/* First-use / 30-day note about who made this. */
.modal{
  position:fixed; inset:0; z-index:40; display:flex; align-items:flex-end;
  justify-content:center; padding:16px; background:rgba(var(--sh),.55);
}
.modal-card{
  width:100%; max-width:460px; background:var(--paper); color:var(--ink);
  border:var(--rule); border-radius:var(--radius); box-shadow:var(--shadow-hard);
  padding:20px 18px calc(18px + env(safe-area-inset-bottom));
}
.modal-card h2{font-size:25px; text-transform:uppercase; letter-spacing:.02em; margin-bottom:10px}
.modal-card .field{margin-bottom:0}
.modal-card textarea{min-height:76px}
.modal-card p{margin:0 0 12px}
.modal-card .btn-row{margin-top:16px}
@media (min-width:520px){ .modal{align-items:center} }
.namerow .rmParent{min-height:48px; padding:12px 13px; font-size:12px; flex:none}

.field{margin-bottom:16px}
.empty-state{text-align:center; padding:34px 12px; color:var(--ink-soft)}
.empty-state h2{color:var(--ink); font-size:24px; margin-bottom:8px}

.toast{
  position:fixed; left:50%; bottom:24px; transform:translateX(-50%);
  background:var(--ink); color:var(--paper); border:1.5px solid var(--ink);
  padding:12px 18px; border-radius:2px; z-index:50; max-width:90vw; text-align:center;
  font-family:var(--label); font-size:14px; letter-spacing:.08em;
  box-shadow:4px 4px 0 rgba(var(--sh),.3);
}
.err{color:var(--rust); font-size:15px; margin-top:6px; font-weight:600}
.notice{
  background:var(--paper-2); border:1.5px solid var(--paper-edge);
  border-left:4px solid var(--ember); border-radius:var(--radius);
  padding:12px 13px; font-size:15px;
}

/* ---- statuses --------------------------------------------------------- */
.tier-growing{--tier:#4f6f3f}
.tier-maintaining{--tier:#a8761c}
.tier-slipping{--tier:#9d3d1a}

.pill.tier-growing,.pill.tier-maintaining,.pill.tier-slipping{
  color:var(--tier); border-color:var(--tier);
  background:color-mix(in srgb, var(--tier) 10%, transparent);
}
.pill.faded{opacity:.45}

.summary{display:flex; gap:8px; margin-bottom:18px}
.sum{
  flex:1; background:var(--card); border:var(--rule);
  border-top:4px solid var(--tier, var(--ink-faint)); border-radius:var(--radius);
  box-shadow:var(--shadow); padding:10px 6px; text-align:center;
}
.sum .n{display:block; font-family:var(--display); font-size:30px; font-weight:800; color:var(--tier, var(--ink)); line-height:1}
.sum .l{display:block; font-family:var(--label); font-size:10px; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--ink-soft); margin-top:3px}
.sum.zero .n{color:var(--ink-faint)}

.topiccard{border-left:5px solid var(--tier, var(--paper-edge)); padding:0}

/* Collapsed Today card: the whole header row is the toggle, so it has to shed
   the letterpress button styling and stay a full-width tap target. */
.topichead{
  width:100%; min-height:56px; padding:13px 14px; margin:0;
  display:flex; align-items:center; gap:12px;
  background:transparent; border:0; border-radius:0; box-shadow:none;
  font-family:var(--body); font-size:16px; letter-spacing:0; text-transform:none;
  text-align:left; color:inherit;
}
.topichead:active{transform:none; box-shadow:none; background:var(--press)}
.th-text{flex:1; min-width:0; display:block}
.th-name{
  display:block; font-family:var(--display); font-size:21px; line-height:1.15;
  letter-spacing:.01em; color:var(--tier, var(--ink));
}
.th-text .muted{display:block; margin-top:1px}
.chev{
  flex:0 0 auto; width:11px; height:11px; margin-right:2px;
  border-right:2px solid var(--ink-soft); border-bottom:2px solid var(--ink-soft);
  transform:rotate(-45deg); transition:transform .12s ease;
}
.topiccard.open .chev{transform:rotate(45deg)}
.topicbody{padding:0 14px 14px; border-top:1px solid var(--paper-edge); margin-top:-1px; padding-top:12px}
.topicbody .picker{margin-top:12px}

.picker{display:flex; gap:6px; margin:12px 0 4px}
.pick{
  flex:1; min-height:44px; padding:8px 3px; font-size:11px; letter-spacing:.08em;
  border-radius:2px; border:1.5px solid var(--ink-faint); background:transparent;
  color:var(--ink-soft); box-shadow:2px 2px 0 rgba(var(--sh),.12);
}
.pick.on{color:var(--on-accent); background:var(--tier); border-color:var(--tier); box-shadow:2px 2px 0 rgba(var(--sh),.28)}

.tierblock{
  background:var(--card); border:var(--rule);
  border-left:5px solid var(--tier, var(--ink)); border-radius:var(--radius);
  box-shadow:var(--shadow); padding:14px; margin:14px 0;
}
.tierblock>h3{font-size:20px; color:var(--tier, var(--ink)); text-transform:uppercase; letter-spacing:.04em}
.tierblock.current{box-shadow:0 0 0 2px var(--tier), var(--shadow)}
.tierblock .field:last-child{margin-bottom:0}

a.card.tier-growing,a.card.tier-maintaining,a.card.tier-slipping{border-left:5px solid var(--tier)}

.kv{margin-top:11px}
.kv .k{
  display:block; font-family:var(--label); font-size:11px; font-weight:600;
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink-soft);
}
.kv .v{display:block; white-space:pre-wrap; overflow-wrap:anywhere; margin-top:1px}
.kv .v.empty{color:var(--ink-faint); font-style:italic}
.small.empty{font-style:italic}

.vh{font-size:26px; margin-bottom:12px; text-transform:uppercase; letter-spacing:.03em}
.notice button{min-height:40px; padding:8px 12px; margin-left:8px; font-size:12px}

/* Print / PDF: one topic per page, so a parent can hand over a single sheet. */
@page{margin:14mm}
@media print{
  .topbar .tabs,.foot,.btn-row,.toast,.no-print,.picker,.summary,.backlink{display:none !important}
  body{background:#fff; font-size:10.5pt; line-height:1.34}
  .topbar{position:static; border-bottom:1px solid #000; padding:0 0 6px}
  main{padding:0; max-width:none}
  .card,.tierblock,.checkrow,.sum,.signrow{box-shadow:none; background:#fff}

  .printpage{break-after:page; page-break-after:always}
  .printpage:last-child{break-after:auto; page-break-after:auto}

  /* One topic, one sheet. A topic with three statuses is eleven prose boxes,
     and on screen each status sits in a padded, bordered, shadowed card. That
     chrome costs roughly a third of a page and pushed real-length topics onto
     a second sheet — templates fit, so it only showed up with a family's own
     writing. On paper the boxes earn nothing: a heading and a rule separate
     the statuses just as well. Measured with pdfinfo, not by eye. */
  .tierblock{
    break-inside:avoid; page-break-inside:avoid;
    border:0; border-left:0; background:none; box-shadow:none;
    border-radius:0; padding:0; margin:9pt 0 0;
  }
  .tierblock.current{box-shadow:none}
  .tierblock>h3{
    font-size:11pt; letter-spacing:.06em;
    padding-bottom:2pt; margin-bottom:1pt;
    border-bottom:.5pt solid #999;
  }
  /* Both status markers come off on paper. The line under the title went
     first; this drops the "where this is now" tag inside the ladder heading
     too, so a printed topic is the plan itself with no snapshot of where the
     teen happens to be today. A sheet handed over stays true next month. */
  .topicstatus,.nowtag{display:none !important}
  .vh{font-size:15pt; margin-bottom:3pt; letter-spacing:.02em}
  .kv{margin-top:4pt}
  .kv .k{font-size:7.5pt; letter-spacing:.1em}
  .kv .v{margin-top:0}
  .grouphead{margin:10pt 0 4pt}
}

/* Template picker rows. Whole row is the label so the tap target is the line,
   not just the box — this gets used on a phone. */
.tplrow {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 12px; margin-bottom: 8px;
  border: var(--rule); border-radius: var(--radius);
  cursor: pointer; min-height: 44px;
}
.tplrow input { margin-top: 3px; width: 18px; height: 18px; flex: none; }
.tplrow .hint { margin: 0; }

/* Templates, collapsed to one line on the Plan tab. Styled to read like a
   .grouphead so it sits in the page rhythm, but it is a real <details> so it
   works with no JS. The marker is drawn with ::after because Safari on iOS
   will not style the native ::-webkit-details-marker consistently. */
.tpl{ margin:24px 0 0; }
.tpl>summary{
  display:flex; align-items:baseline; gap:8px;
  padding-bottom:5px; border-bottom:1px solid var(--paper-edge);
  font-family:var(--label); font-size:12px; font-weight:600;
  letter-spacing:.2em; text-transform:uppercase; color:var(--ink-soft);
  cursor:pointer; min-height:44px; list-style:none;
}
.tpl>summary::-webkit-details-marker{ display:none; }
.tpl>summary::after{
  content:"+"; margin-left:auto; font-size:17px; line-height:1;
  color:var(--ink-soft);
}
.tpl[open]>summary::after{ content:"–"; }
.tpl>summary:focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }
.tplcount{
  font-size:11px; color:var(--ink-faint); letter-spacing:.1em;
}
.tpl>.hint{ margin-top:10px; }


/* ---- Dark theme: agave ----------------------------------------------------
   Taken from an agave plant: deep blue-green shade for the ground, the pale
   glaucous bloom on the leaf for text, and the reddish-bronze of the marginal
   spines kept as the accent — which is why the rust survives here rather than
   being swapped out for another green.

   Two values are NOT simple inversions:
   --line is its own token instead of reusing --ink, because near-white text
   colour on 1.5px card borders turns every card into a glaring white box. It
   sits at 3.6:1 — over the 3:1 a component boundary needs, well under text.
   --on-accent flips to the dark ground, because the accents brighten here and
   cream on bright terracotta falls to about 2.6:1.

   Every text pair was measured; the lowest is --ink-faint at 5.5:1. */
html[data-theme="dark"]{
  --paper:#12201d; --paper-2:#182a26; --paper-3:#1f342f; --paper-edge:#3d5c53;
  --ink:#e3f1e7; --ink-2:#c8dcce; --ink-soft:#a3bcae; --ink-faint:#82998d;
  --rust:#e0865a; --rust-bright:#ef9a71; --sage:#7fae90; --ember:#e0a45c;

  --line:#557d6f;
  --card:rgba(198,235,214,.055);
  --card-2:rgba(198,235,214,.085);
  --press:rgba(227,241,231,.07);
  --on-accent:#12201d;
  --sh:0,0,0;

  /* Pure black at .13 is invisible on a dark ground, so the letterpress
     shadows lean harder here instead of being dropped. */
  --shadow:4px 4px 0 rgba(0,0,0,.42);
  --shadow-hard:3px 3px 0 rgba(0,0,0,.55);
  color-scheme:dark;
}
html[data-theme="dark"] .tier-growing{--tier:#86b96e}
html[data-theme="dark"] .tier-maintaining{--tier:#dcab4e}
html[data-theme="dark"] .tier-slipping{--tier:#e8836a}

/* Dark-mode toggle, bottom of the Share tab. The whole row is the tap target,
   so the switch is not the only thing worth hitting. */
.themerow{
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding:12px 14px; margin-top:10px; min-height:56px;
  background:var(--card); border:var(--rule); border-radius:var(--radius);
}
.themelabel{
  font-family:var(--label); font-size:14px; font-weight:600;
  letter-spacing:.1em; text-transform:uppercase;
}
.themerow .hint{ margin:3px 0 0; }
/* 44px tall, not the 36 a switch usually gets — the suite asserts every
   control clears 44 and this one is no exception. */
.switch{
  flex:none; width:72px; min-width:72px; height:44px; min-height:44px;
  padding:0; border:var(--rule); border-radius:999px;
  background:var(--paper-3); box-shadow:none; position:relative; cursor:pointer;
}
.switch::after{
  content:""; position:absolute; top:5px; left:5px;
  width:32px; height:32px; border-radius:50%; background:var(--ink);
  transition:transform .16s ease, background .16s ease;
}
.switch[aria-checked="true"]{ background:var(--sage); border-color:var(--sage); }
.switch[aria-checked="true"]::after{ transform:translateX(28px); background:var(--on-accent); }
.switch:active{ transform:none; box-shadow:none; }
.switch:focus-visible{ outline:2px solid var(--line); outline-offset:2px; }
@media (prefers-reduced-motion:reduce){ .switch::after{ transition:none; } }

/* ---- Print forces the light palette -------------------------------------
   MUST stay at the end of the file. It targets html[data-theme="dark"], the
   same selector the theme block above uses, so it only wins on source order —
   putting it back up with the other print rules silently stops it working and
   a dark-mode print comes out pale-on-white. The suite asserts this. */
@media print{
  html[data-theme="dark"]{
    --paper:#ece0c6; --paper-2:#e3d5b6; --paper-3:#d8c8a4; --paper-edge:#c9b691;
    --ink:#1b201c; --ink-2:#2c342d; --ink-soft:#4a544a; --ink-faint:#6d766c;
    --rust:#9d3d1a; --rust-bright:#bd5426; --sage:#5d6b54; --ember:#c9782d;
    --line:#1b201c; --on-accent:#fdf6e6; --sh:27,32,28;
    --card:rgba(255,251,240,.55); --card-2:rgba(255,251,240,.75);
    --press:rgba(27,32,28,.05);
    --shadow:4px 4px 0 rgba(27,32,28,.13);
    --shadow-hard:3px 3px 0 rgba(27,32,28,.35);
    color-scheme:light;
  }
  html[data-theme="dark"] .tier-growing{--tier:#4f6f3f}
  html[data-theme="dark"] .tier-maintaining{--tier:#a8761c}
  html[data-theme="dark"] .tier-slipping{--tier:#9d3d1a}
}
