/* teal-sea — the Stitch template, rebuilt.
 *
 * Same layout and voice as the mockups; none of their machinery. Stitch ships
 * Tailwind from a CDN plus three font requests; this is one stylesheet and two
 * families. The fonts are still Google-hosted here so the preview is quick to
 * look at — self-hosting them is a swap of one @font-face block and takes the
 * page back to zero third-party fetches.
 */

:root{
  /* light */
  --paper:#fbf9f9;
  --ink:#1b1c1c;
  --soft:#6f7979;          /* the mockup's `outline` — mono metadata */
  --hair:#bec9c8;          /* the mockup's `outline-variant` — the rules */
  --mark:#0f6b68;          /* teal-sea's own teal, kept over Stitch's #004c4c */
  --link:#1b1c1c;
  --seen:#1b1c1c;

  --sans:"Geist","Helvetica Neue",Helvetica,Arial,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  /* type: sans carries the names, mono carries everything machine-ish */
  --t-display:3rem;        /* 48 — the wordmark */
  --t-proj:2rem;           /* 32 — a project name */
  --t-head:1.5rem;         /* 24 — section headings */
  --t-body:1rem;           /* 16 */
  --t-meta:.875rem;        /* 14 — mono metadata */
  --t-label:.75rem;        /* 12 — nav, footer */

  --measure:68ch;
  --gutter:clamp(1.15rem,4vw,2.5rem);
}

/* THREE STATES, in this order:
     1. no choice made  -> follow the operating system
     2. chose dark      -> dark, whatever the system says
     3. chose light     -> light, whatever the system says
   The :not([data-theme="light"]) is what makes 3 possible: without it a
   reader on a dark machine could never get back to the paper. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --paper:#000000;
    --ink:#f2f2f2;
    --soft:#9a9a9a;
    --hair:#2a2a2a;
    --mark:#5fb8b2;
    --link:#f2f2f2;
    --seen:#f2f2f2;
  }
}
:root[data-theme="dark"]{
  --paper:#000000;
  --ink:#f2f2f2;
  --soft:#9a9a9a;
  --hair:#2a2a2a;
  --mark:#5fb8b2;
  --link:#f2f2f2;
  --seen:#f2f2f2;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font:var(--t-body)/1.6 var(--sans);
  -webkit-font-smoothing:antialiased;
}

/* ---- the bar across the top ------------------------------------------- */
.topnav{border-bottom:1px solid var(--hair); position:sticky; top:0;
        background:var(--paper); z-index:5}
.topnav-in{max-width:80rem; margin:0 auto; padding:.9rem var(--gutter);
           display:flex; align-items:center; gap:1rem 2rem; flex-wrap:wrap}
/* The slash carries the teal; the word is ink. The whole lockup in teal and
   bold reads as a logo bolted to the corner — this reads as the name of the
   place, and it matches the big wordmark further down the page. */
.wordmark{font-weight:500; font-size:1.25rem; letter-spacing:-.02em;
          color:var(--ink); text-decoration:none; margin-right:auto}
.wordmark .slash{color:var(--mark)}
.sections{display:flex; gap:1.6rem; font-family:var(--mono);
          font-size:var(--t-label); letter-spacing:.06em}
.sections a{color:var(--soft); text-decoration:none; padding-bottom:2px}
.sections a:hover{color:var(--ink)}
.sections a[aria-current]{color:var(--ink); border-bottom:1px solid var(--mark)}
.themetoggle{font-family:var(--mono); font-size:var(--t-label); letter-spacing:.06em;
             color:var(--soft); background:none; border:0; padding:0; cursor:pointer}
.themetoggle:hover{color:var(--ink)}
.themetoggle:focus-visible,.sections a:focus-visible,.wordmark:focus-visible{
  outline:2px solid var(--mark); outline-offset:3px}

/* ---- the page --------------------------------------------------------- */
.page{max-width:80rem; margin:0 auto; padding:clamp(2rem,6vw,4.5rem) var(--gutter) 5rem}
h1{font-size:var(--t-display); font-weight:500; letter-spacing:-.02em;
   line-height:1.1; margin:0}
.slash{color:var(--mark)}
.strap{font-family:var(--mono); font-size:var(--t-meta); color:var(--soft);
       margin:.5rem 0 0}
.rule{height:1px; background:var(--hair); margin:2.5rem 0 0}

/* ---- the directory ----------------------------------------------------- */
.directory{list-style:none; margin:0; padding:0; max-width:62rem}
.directory li{
  display:grid;
  grid-template-columns:1fr auto;
  align-items:baseline;
  gap:.25rem 2rem;
  padding:1.6rem 0;
  border-bottom:1px solid var(--hair);
}
.proj{font-size:var(--t-proj); font-weight:500; letter-spacing:-.02em;
      color:var(--link); text-decoration:none; border-bottom:2px solid currentColor;
      justify-self:start; line-height:1.2}
.proj:visited{color:var(--seen)}
.proj:hover{color:var(--mark); border-bottom-color:var(--mark)}
.proj:focus-visible{outline:2px solid var(--mark); outline-offset:4px}
.meta{font-family:var(--mono); font-size:var(--t-meta); color:var(--soft);
      text-align:right; grid-column:2}
.status{font-family:var(--mono); font-size:var(--t-meta); color:var(--mark);
        text-align:right; grid-column:2}

/* ---- the log ----------------------------------------------------------- */
h2{font-size:var(--t-head); font-weight:500; letter-spacing:-.02em;
   margin:4.5rem 0 1.6rem; scroll-margin-top:5rem}
.log{list-style:none; margin:0; padding:0; max-width:62rem}
.log li{display:grid; grid-template-columns:7.5rem 1fr; gap:0 1.6rem;
        padding:.55rem 0; align-items:baseline}
.log li + li{margin-top:.15rem}
.log time{font-family:var(--mono); font-size:var(--t-meta); color:var(--soft)}
/* which tree the line came out of. nowrap so the name never breaks across
   lines, and it is allowed to fall to its own line rather than stretch the
   sentence above it. */
.src{color:var(--soft); white-space:nowrap; opacity:.75}
.src::before{content:"— "}
.built{color:var(--soft)}
/* the direct child only: ".log span" also matched the .src tag nested inside
   it, so every repo name drew its own rule and its own 1.6rem indent, which is
   what put stray vertical bars in the middle of the lines */
/* ONE rule down the whole log, not one per entry.
   A border-left on each entry only spans that entry's text, so every rule
   stopped 12px short of the separator above and below it and the column read
   as a column of floating stubs. This is a single line drawn behind the list,
   at the column boundary, so it is continuous by construction. */
.log{position:relative}
.log::before{content:""; position:absolute; top:0; bottom:0;
             left:calc(7.5rem + .8rem); width:1px; background:var(--hair)}
.log li > span{font-family:var(--mono); font-size:var(--t-meta); line-height:1.7;
          padding-left:.8rem; max-width:var(--measure)}

/* ---- the foot ---------------------------------------------------------- */
.foot{border-top:1px solid var(--hair)}
.foot-in{max-width:80rem; margin:0 auto; padding:1.4rem var(--gutter);
         display:flex; justify-content:space-between; gap:1rem 2rem; flex-wrap:wrap;
         font-family:var(--mono); font-size:var(--t-label); color:var(--soft);
         letter-spacing:.06em}
.foot-links{display:flex; gap:1.4rem}
.foot a{color:var(--soft); text-decoration:none}
.foot a:hover{color:var(--ink)}
.foot a:focus-visible{outline:2px solid var(--mark); outline-offset:3px}

/* ---- narrow ------------------------------------------------------------ */
@media (max-width:40rem){
  :root{--t-display:2.25rem; --t-proj:1.5rem}
  .directory li{grid-template-columns:1fr; gap:.35rem}
  .meta,.status{text-align:left; grid-column:1}
  .status{margin-top:-.15rem}
  .log li{grid-template-columns:1fr; gap:.25rem}
  .log span{border-left:0; padding-left:0}
  .sections{gap:1.1rem}
}

@media print{
  :root{--paper:#fff; --ink:#000; --soft:#333; --hair:#bbb; --mark:#000}
  .topnav{position:static; border-bottom:1px solid #bbb}
  .themetoggle{display:none}
  .directory li,.log li{break-inside:avoid}
}

/* ---- prose pages: the case study and the record ------------------------ */
.prose{max-width:56rem}
.prose .strap{margin:.7rem 0 0; max-width:var(--measure)}
.prose section{margin:3.2rem 0 0}
.prose h2{display:grid; grid-template-columns:max-content 1fr; gap:0 .9rem;
          align-items:baseline; margin:0 0 1rem}
.prose h2 .n{font-family:var(--mono); font-size:var(--t-meta); color:var(--mark);
             font-variant-numeric:tabular-nums}
.prose p{max-width:var(--measure); margin:0 0 1rem}
.prose .lede{font-size:1.25rem; letter-spacing:-.01em}
.prose .rules{list-style:none; margin:0 0 1rem; padding:0; max-width:var(--measure);
              font-family:var(--mono); font-size:var(--t-meta); line-height:1.9}
.prose .rules b{color:var(--ink); font-weight:500}
.prose .stack,.prose .facts{font-family:var(--mono); font-size:var(--t-meta);
                            color:var(--soft); max-width:none}
.prose .closer{font-size:1.25rem; letter-spacing:-.01em; margin-top:2rem}
.prose .go a{color:var(--mark); text-decoration:none; border-bottom:1px solid var(--mark)}
.prose .rule{margin:2.5rem 0}

/* ---- the evidence thumbnail -------------------------------------------
   Complete, never cropped. The first attempt was a fixed-height band with
   object-fit:cover, which sliced straight through whatever happened to sit at
   that height — half a formula, the top of "$48,200", a row of the interface
   cut at the baseline. A screenshot cropped to a strip is not evidence, it is
   damage. Small and whole beats large and sliced. */
.shot{grid-column:1 / -1; display:block; margin:1.15rem 0 .15rem;
      width:min(360px,52%); border:1px solid var(--hair);
      overflow:hidden; line-height:0}
.shot img{display:block; width:100%; height:auto;
          filter:saturate(.92); transition:filter .15s linear, opacity .15s linear}
.directory li:hover .shot img{filter:none}
:root[data-theme="dark"] .shot img{opacity:.85}
:root[data-theme="dark"] .directory li:hover .shot img{opacity:1}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .shot img{opacity:.85}
  :root:not([data-theme="light"]) .directory li:hover .shot img{opacity:1}
}
@media (max-width:40rem){ .shot{width:100%} }
@media (prefers-reduced-motion:reduce){ .shot img{transition:none} }

/* On a phone the bar wrapped to three rows and left the theme control alone on
   the third, reading as an orphan rather than a control. The wordmark takes
   its own line; the sections and the control share the next one. */
/* (an earlier wrap fix lived here; the hamburger replaced it) */

/* =======================================================================
   MOBILE, from the mobile mockups rather than from folding the desktop one.
   Those exports specify four things the desktop export does not: a hamburger
   instead of a nav row, [ bracket ] labels heading each block, the status
   bracketed and inline with the category, and a log set in the sans with a
   short date. All four are narrow-only.
   ======================================================================= */

/* the bracket labels are a mobile device; the desktop mockups have none */
.blocklabel{display:none}

/* the hamburger, likewise */
.menu{display:none; background:none; border:0; padding:.35rem; cursor:pointer;
      margin-left:auto; width:2rem}
.menu span{display:block; height:1.5px; background:var(--ink); margin:4px 0;
           transition:transform .18s ease, opacity .18s ease}
.menu[aria-expanded="true"] span:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
.menu[aria-expanded="true"] span:nth-child(2){opacity:0}
.menu[aria-expanded="true"] span:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}
.menu:focus-visible{outline:2px solid var(--mark); outline-offset:3px}
.status i{font-style:normal; color:var(--soft)}

@media (max-width:40rem){
  .blocklabel{display:block; font-family:var(--mono); font-size:var(--t-label);
              letter-spacing:.14em; color:var(--soft); margin:2.2rem 0 .2rem}
  .menu{display:block}

  /* the bar is wordmark and hamburger on one line, nothing else; everything
     else lives in the panel the hamburger opens, the control included */
  .sections{display:none; flex:0 0 100%; flex-direction:column;
            align-items:flex-start; gap:.9rem;
            padding:.9rem 0 .3rem; font-size:var(--t-meta)}
  .sections.open{display:flex}
  .topnav-in{gap:0 1rem; flex-wrap:wrap}
  .wordmark{flex:0 1 auto; margin-right:auto}
  .sections .themetoggle{margin-left:0; font-size:var(--t-meta)}

  /* the bracket label heads the block; the heading would say it twice */
  .page > h2{display:none}
  .blocklabel + h2{display:none}

  /* name, then category and status on one line, the status in brackets */
  .directory li{grid-template-columns:1fr; gap:.3rem; padding:1.3rem 0}
  .meta,.status{text-align:left; grid-column:1}
  .status{display:inline; margin-top:0}
  .directory li .meta{display:inline}
  .directory li .meta::after{content:" "}

  /* the log: sans, a short date, a rule between entries */
  .log li{grid-template-columns:3.2rem 1fr; gap:0 .9rem; padding:.75rem 0}
  .log li + li{border-top:1px solid var(--hair); margin-top:0}
  .log time{font-size:var(--t-label); text-align:right}
  .log::before{left:calc(3.2rem + .45rem)}
  .log li > span{font-family:var(--sans); font-size:1rem; line-height:1.45;
                 padding-left:.45rem}
}
.log time .short{display:none}
@media (max-width:40rem){
  .log time .long{display:none}
  .log time .short{display:inline}
}
