/* Shared by the hub (index.html) and the news page (whats-new/index.html).
   Inter, self-hosted: Latin, weights 400-700 (the pages use 400 to 700). Licence: fonts/OFL.txt. */
@font-face{font-family:'Inter';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('fonts/inter-latin-normal.woff2') format('woff2')}
/* Both blocks copied verbatim from induction/frontend-internal/src/styles/theme.css (:root and
   .dark), the tokens these pages use. If the apps' theme moves, these copies go stale.
   theme.js puts .light or .dark on <html>. */
:root{
  --radius:0.625rem;
  --background:oklch(1 0 0);
  --foreground:oklch(0.145 0.012 265);
  --card:oklch(1 0 0);
  --card-foreground:oklch(0.145 0.012 265);
  --primary:oklch(0.45 0.19 255);
  --primary-foreground:oklch(0.985 0.005 250);
  --muted-foreground:oklch(0.51 0.014 265);
  --accent:oklch(0.968 0.004 265);
  --accent-foreground:oklch(0.21 0.012 265);
  --border:oklch(0.922 0.005 265);
}
:root.dark{
  --background:oklch(0.145 0.008 265);
  --foreground:oklch(0.97 0.004 265);
  --card:oklch(0.205 0.009 265);
  --card-foreground:oklch(0.97 0.004 265);
  --primary:oklch(0.72 0.15 250);
  --primary-foreground:oklch(0.18 0.04 260);
  --muted-foreground:oklch(0.72 0.015 265);
  --accent:oklch(0.275 0.009 265);
  --accent-foreground:oklch(0.97 0.004 265);
  --border:oklch(1 0 0 / 12%);
}
/* Hub-only, not in theme.css. In light the page sits a step below its white cards; in dark
   it is the apps' --background and the cards stand off by their own lightness. --mark is
   the hero logo's opacity. */
:root{--page:oklch(0.985 0.002 265); --mark:.07; color-scheme:light;
  /* An outline button's border is its only boundary: --border is 1.2:1 on the page, it needs 3:1. */
  --control-border:var(--muted-foreground);
  --shadow:0 1px 2px oklch(0.145 0.012 265 / 4%),0 12px 32px -16px oklch(0.145 0.012 265 / 14%);
  --font-sans:'Inter',sans-serif}
:root.dark{--page:var(--background); --mark:.1; --shadow:none; color-scheme:dark}

*{box-sizing:border-box;margin:0;padding:0}
/* The hero mark runs past the container's right edge and, on a narrow screen, past the viewport.
   Both lines are needed: with html clipped, body clips itself at the viewport edge instead of
   handing its overflow to the viewport, which on a phone widens the page. */
html{-webkit-font-smoothing:antialiased; overflow-x:clip}
body{font-family:var(--font-sans); background:var(--page); color:var(--foreground);
  min-height:100svh; display:flex; flex-direction:column; line-height:1.5; overflow-x:clip}
a{cursor:pointer}
/* The hub copies no --ring: focus is a --primary outline, offset clear of the control's own fill. */
:where(a,button):focus-visible{outline:2px solid var(--primary); outline-offset:2px}
.sr-only{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}

.container{width:100%; max-width:1200px; margin:0 auto; padding-inline:clamp(20px,3vw,32px);
  flex:1; display:flex; flex-direction:column}

/* The header, on both pages. */
header{display:flex; align-items:center; justify-content:space-between; gap:1rem;
  min-height:72px; border-bottom:1px solid var(--border)}
.brand{display:flex; align-items:center; gap:10px; min-height:44px; color:inherit; text-decoration:none;
  border-radius:6px}
.brand img{width:30px; height:30px; display:block}
.brand span{font-size:1rem; font-weight:600; letter-spacing:-.01em}
.header-end{display:flex; align-items:center; gap:12px}
.env-tag{display:inline-flex; align-items:center; height:24px; padding-inline:10px; border-radius:999px;
  border:1px solid var(--border); background:var(--accent); color:var(--accent-foreground);
  font-size:.75rem; font-weight:500}
.env-tag[hidden]{display:none}
.theme-toggle{width:40px; height:40px; display:flex; align-items:center; justify-content:center; padding:0;
  border:1px solid var(--control-border); border-radius:8px; background:var(--card); color:var(--foreground);
  cursor:pointer; transition:background-color .15s ease}
.theme-toggle:hover{background:var(--accent)}
.theme-toggle svg{width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round}
/* The icon shows the theme in use. Without JavaScript there is no theme class and nothing to switch. */
.theme-toggle .moon, :root.dark .theme-toggle .sun{display:none}
:root.dark .theme-toggle .moon{display:block}
:root:not(.light):not(.dark) .theme-toggle{display:none}

/* The hub. */
.hub main{flex:1; padding-bottom:64px}
/* The mark runs past the container's edge and the hero's bottom, and up under the header: nothing
   clips it. Its top fades out by mask, fully clear by the page top (78px = the 150px it rises above
   the hero minus the 72px header), so no straight edge shows anywhere; the header sits above it. */
header{position:relative; z-index:1}
.hero{position:relative; padding:64px 0 44px}
.hero-mark{position:absolute; right:-90px; top:-150px; width:520px; height:520px; opacity:var(--mark);
  pointer-events:none;
  -webkit-mask-image:linear-gradient(to bottom,transparent 78px,#000 250px);
  mask-image:linear-gradient(to bottom,transparent 78px,#000 250px)}
.hero-text{position:relative; max-width:960px}
.hero h1{font-size:clamp(32px,4.4vw,52px); font-weight:700; letter-spacing:-.03em; line-height:1.08; text-wrap:balance}
/* A step darker than --muted-foreground: on a narrow screen the faint logo sits behind this line
   and the plain token drops under 4.5:1. */
.hero p{margin-top:14px; font-size:18px; color:color-mix(in oklch,var(--muted-foreground) 90%,var(--foreground))}

.panel{background:var(--card); color:var(--card-foreground); border:1px solid var(--border);
  border-radius:16px; box-shadow:var(--shadow); position:relative}
.systems{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr)); gap:24px}
.system{display:flex; flex-direction:column; gap:16px; padding:28px}
.system h2{font-size:28px; font-weight:600; letter-spacing:-.02em; line-height:1.2}
.system .desc{margin-top:6px; font-size:15px; color:var(--muted-foreground)}
.actions{display:flex; flex-wrap:wrap; gap:8px; margin-top:8px}
.action{display:inline-flex; align-items:center; gap:8px; height:44px; padding-inline:16px; border-radius:8px;
  border:1px solid var(--control-border); color:inherit; font-size:15px; font-weight:500; text-decoration:none;
  transition:background-color .15s ease,opacity .15s ease}
.action.primary{padding-inline:20px; border-color:transparent; background:var(--primary); color:var(--primary-foreground)}
.action.primary:hover{background:var(--primary); opacity:.9}
.action svg{width:16px; height:16px; flex:none; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; transition:transform .15s ease}
.action.primary:hover svg{transform:translateX(2px)}

/* What's new on the hub: the newest two releases. whats-new.js fills it and shows it. */
.hub-news{margin-top:24px; padding:20px 28px 8px}
.hub-news[hidden]{display:none}
.hub-news h2{font-size:17px; font-weight:600}
.hub-news h2 a{display:inline-flex; align-items:center; gap:8px; min-height:44px; color:inherit; text-decoration:none;
  border-radius:6px}
.hub-news h2 a:hover{text-decoration:underline; text-underline-offset:3px}
.hub-news h2 svg{width:18px; height:18px; fill:none; stroke:var(--muted-foreground); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round}
.dot{width:8px; height:8px; border-radius:999px; background:var(--primary); flex:none}
.releases{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr)); column-gap:40px}
.release{display:flex; flex-direction:column; gap:6px; padding:16px 0; border-top:1px solid var(--border);
  color:inherit; text-decoration:none}
.release .title{font-size:16px; font-weight:600; line-height:1.4; text-underline-offset:3px}
.release:hover .title{text-decoration:underline}
.release .summary{font-size:14px; color:var(--muted-foreground)}
.release .chip{height:22px; padding-inline:8px; border-radius:999px; border:1px solid var(--border)}

footer{display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:16px;
  padding:20px 0 24px; border-top:1px solid var(--border); font-size:13px; color:var(--muted-foreground)}
footer .fl{display:flex; flex-wrap:wrap; align-items:center; gap:8px 16px}
footer b{color:var(--foreground); font-weight:500}
/* 44px tall to the finger, 20px to the layout. */
footer .fl a{display:inline-flex; align-items:center; min-height:44px; margin-block:-12px; color:inherit}
footer .pb{display:flex; align-items:center; gap:10px}
footer .pb .by{font-size:11px; letter-spacing:.12em; text-transform:uppercase}
footer .pb img{width:auto; display:block}
footer .pb .ic{height:22px}
footer .pb .wm{height:13px}

/* The news page (whats-new/index.html). */
.news-page main{flex:1; display:flex; flex-direction:column; width:100%; max-width:48rem;
  padding-block:clamp(2.5rem,7vh,4.5rem)}
.lead{padding-bottom:1.75rem; border-bottom:1px solid var(--border); margin-bottom:2.5rem}
.lead h1{font-size:1.875rem; font-weight:600; letter-spacing:-.02em; line-height:1.1}
.lead p{margin-top:.5rem; font-size:.9375rem; color:var(--muted-foreground)}
/* 44px tall to the finger, the same height as before to the layout. */
.back{display:inline-flex; align-items:center; gap:.375rem; min-height:44px; margin-block:-12px 9px;
  font-size:.875rem; font-weight:500; color:var(--muted-foreground); text-decoration:none}
.back:hover{color:var(--foreground)}
.back:focus-visible{border-radius:2px}
.back svg{width:1rem; height:1rem; stroke:currentColor; stroke-width:2; fill:none}
.month + .month{margin-top:3rem}
.month h2{font-size:1.25rem; font-weight:600; letter-spacing:-.01em; margin-bottom:.5rem}

/* One text row per release, divided by hairlines; the release opens in the dialog.
   The negative margin lines the text up with the heading while the hover fill bleeds. */
.entries{display:flex; flex-direction:column}
.entry{position:relative; display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:2rem; row-gap:.375rem;
  padding:1.25rem .75rem; margin-inline:-.75rem; border-radius:calc(var(--radius) - 2px);
  color:inherit; text-decoration:none; transition:background-color .15s ease}
.entry + .entry::before{content:""; position:absolute; top:0; left:.75rem; right:.75rem; height:1px; background:var(--border)}
.entry:hover{background:color-mix(in oklch,var(--accent) 45%,transparent)}
.entry:focus-visible{outline-offset:0}
.entry > *{grid-column:1}
.entry .title{font-size:1rem; font-weight:600; line-height:1.4; text-underline-offset:3px}
.entry:hover .title{text-decoration:underline}
.entry .summary{font-size:.875rem; color:var(--muted-foreground);
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; line-clamp:2; overflow:hidden}
.entry .systems{grid-column:2; grid-row:1 / span 3; align-self:center; text-align:right;
  font-size:.75rem; font-weight:500; color:var(--muted-foreground); white-space:nowrap}
/* The date and one label per type of change: a list row, the open release and the hub. */
.post-meta{display:flex; align-items:center; flex-wrap:wrap; gap:.375rem;
  font-size:.8125rem; color:var(--muted-foreground)}
.post-meta .date{margin-right:.375rem; font-variant-numeric:tabular-nums}
.chip{display:inline-flex; align-items:center; height:1.25rem; padding-inline:.4375rem;
  border-radius:calc(var(--radius) - 6px); background:var(--accent); color:var(--accent-foreground);
  font-size:.75rem; font-weight:500; line-height:1}

/* The open post. Styled from the tokens, not .panel: a display rule there would show a closed dialog. */
.post-dialog{margin:auto; width:calc(100% - 2rem); max-width:44rem; max-height:calc(100svh - 4rem);
  padding:0; border:1px solid var(--border); border-radius:calc(var(--radius) + 4px);
  background:var(--card); color:var(--card-foreground); box-shadow:0 1px 2px 0 rgb(0 0 0 / .05)}
.post-dialog::backdrop{background:rgb(0 0 0 / .5)}
.post-dialog[open]{display:flex; flex-direction:column; overflow:hidden}
.post-dialog .inner{flex:1 1 auto; min-height:0; overflow-y:auto}
.post-dialog .bar{position:sticky; top:0; z-index:1; display:flex; align-items:center; justify-content:space-between;
  gap:.75rem; padding:.75rem 1rem; background:var(--card); border-bottom:1px solid var(--border)}
.post-dialog .nav{display:flex; gap:.5rem}
.post-full{display:flex; flex-direction:column; gap:.75rem; padding:1.5rem}
.post-head{display:flex; flex-direction:column; gap:.625rem}
.post-full h2{font-size:1.5rem; font-weight:600; line-height:1.25; letter-spacing:-.015em}
.post-full p{font-size:.9375rem}
.post-full .more{color:var(--muted-foreground)}
/* No width:100% and no flex stretch: the 2x srcset keeps a picture at its size in the app. */
.post-full img{display:block; align-self:flex-start; max-width:100%; height:auto; margin-top:.375rem; border:1px solid var(--border);
  border-radius:calc(var(--radius) - 2px)}
.changes{display:flex; flex-direction:column; gap:1rem; margin-top:.75rem; padding-top:1.25rem; border-top:1px solid var(--border)}
.changes h3{font-size:1rem; font-weight:600}
.change{display:flex; flex-direction:column; gap:.375rem}
.change .change-title{font-size:.9375rem; font-weight:600; line-height:1.4}
.sys{font-size:.75rem; font-weight:500; color:var(--muted-foreground)}
.compact{padding-left:1.25rem; display:flex; flex-direction:column; gap:.625rem; font-size:.9375rem}
.compact .sys{display:block}
html.dialog-open{overflow:hidden}

/* The dialog's controls. */
.btn{display:inline-flex; align-items:center; gap:.5rem; height:2.25rem; padding-inline:1rem;
  border-radius:calc(var(--radius) - 2px); font-family:inherit; font-size:.875rem; font-weight:500; cursor:pointer;
  transition:background-color .15s ease}
.btn.outline{background:transparent; color:var(--foreground); border:1px solid var(--control-border)}
.btn.outline:hover:not(:disabled){background:var(--accent)}
.btn.square{width:2.25rem; padding:0; justify-content:center}
.btn svg{width:1rem; height:1rem; stroke:currentColor; stroke-width:2; fill:none}
.btn:disabled{opacity:.5; cursor:default}
.status{font-size:.9375rem; color:var(--muted-foreground)}

@media (max-width:720px){
  .entry{grid-template-columns:minmax(0,1fr)}
  .entry .systems{grid-column:1; grid-row:auto; text-align:left}
  .post-dialog{width:100%; max-width:none; height:100%; max-height:none; border:0; border-radius:0}
  .post-full{padding:1.25rem}}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
