:root {
  --bg: #fbfaf8;
  --fg: #16161a;
  --dim: #6b6b76;
  --line: #e2e0da;
  --accent: #ff6600; /* HN orange — fills, dots, focus rings */
  --link: #b34700; /* orange for text: HN orange is 2.8:1 on this paper, this is 5.3:1 */
  --sheet: #ffffff;
  --outside: #d9d7d1; /* desktop surround, outside the phone */
  --mark: rgba(255, 138, 51, .42);
  --tint: rgba(255, 102, 0, .07);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0f0f10;
    --link: #ff6600; /* 6.5:1 on the dark background */
    --fg: #f2f1ee;
    --dim: #9a9aa4;
    --line: #2a2a2e;
    --sheet: #17171a;
    --outside: #000;
    --mark: rgba(255, 122, 26, .34);
    --tint: rgba(255, 138, 51, .10);
  }
}
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  background: var(--outside);
  color: var(--fg);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
  display: grid;
  place-items: center;
}

/* The phone. Full bleed on a real phone, a centred column everywhere else —
   which is how Reels and Shorts behave on desktop. All chrome positions
   against THIS, not the viewport, or it would cling to the browser window. */
.phone {
  position: relative;
  isolation: isolate;
  width: 100%;
  max-width: 390px;
  height: 100dvh;
  overflow: hidden;
  background: var(--bg);
}
@media (min-width: 481px) {
  .phone {
    height: min(100dvh - 40px, 844px); /* 390x844, a typical phone rather than the largest */
    border-radius: 30px;
    box-shadow: 0 24px 70px rgba(0, 0, 0, .34), 0 0 0 1px rgba(0, 0, 0, .06);
  }
  /* 7vw measures the browser window, not the frame, so it pins at the 34px cap
     here; 29px, a notch under the old 34-in-430 proportion. */
  .phone .simple { font-size: 29px; } /* beats the base rule declared below */
}

/* vertical axis: one post per screen */
#feed {
  height: 100%;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  overscroll-behavior-y: contain;
  scrollbar-width: none;
}
#feed::-webkit-scrollbar { display: none; }
#feed.locked { overflow-y: hidden; }

/* horizontal axis: depth within one post */
.post {
  height: 100%;
  scroll-snap-align: start;
  /* Without this a fast flick carries past a snap point and skips a post. */
  scroll-snap-stop: always;
  display: flex;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.post::-webkit-scrollbar { display: none; }

.card {
  flex: 0 0 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 84px 36px 132px;
  min-width: 0;
}
/* The glance layer is the biggest: it is the only one most readers ever see. */
/* Display text wants tighter leading; body text wants looser. */
.simple { font-size: clamp(25px, 6.5vw, 32px); font-weight: 680; letter-spacing: -0.022em; line-height: 1.2; margin: 0; }
.substance { font-size: 16px; line-height: 1.62; margin: 0; }

/* The glance card, text low like a caption. With an image, the whole image is
   shown, contained in the space above the text, on the plain card — never
   cropped to fill: a 1200x630 social card cropped to this frame keeps 24% of
   its width. Without one, the card gets a clipping: the original HN title as a
   newspaper headline in the image's place, over a glow in a colour derived from
   the post id. Same plain card either way, so the scroll has one rhythm. */
.card.glance { position: relative; overflow: hidden; justify-content: flex-end; padding-bottom: 92px; } /* just clear of the buttons */
.pic { position: relative; flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; margin-bottom: 28px; }
/* The whole image, never cropped, framed crisply over its own blurred colour. */
.pic .shot {
  position: relative; z-index: 1; display: block; max-width: 100%; max-height: 100%;
  border-radius: 12px; box-shadow: 0 8px 28px rgba(0, 0, 0, .18);
}
/* A blurred copy fills the whole card with the image's colour — the old
   full-bleed mood, without cropping the picture itself. It fades out before the
   text, so the caption sits on the plain card and keeps its contrast. */
.card.glance > .glow {
  position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%;
  object-fit: cover; filter: blur(48px) saturate(1.4); transform: scale(1.25); opacity: .7;
  mask-image: linear-gradient(to bottom, #000 50%, transparent 82%);
  -webkit-mask-image: linear-gradient(to bottom, #000 50%, transparent 82%);
}
/* A newspaper clipping: black headline on paper, in both themes — it is an
   object on the card, like a photo, not part of the page. The headline is the
   original HN title, verbatim, so it needs no checking. */
.clip {
  position: relative; z-index: 1; flex: none; width: calc(100% + 44px); /* past the text column, 14px from the card edge */
  background: #fbf9f3; color: #141414; padding: 16px 20px 22px;
  border-radius: 2px; box-shadow: 0 10px 30px rgba(0, 0, 0, .2);
  transform: rotate(var(--tilt, -1deg));
}
.clip .mast {
  font-size: 10.5px; font-weight: 650; letter-spacing: .16em; text-transform: uppercase; color: #5a5a5a;
  text-align: center; padding-bottom: 9px; margin-bottom: 14px; border-bottom: 3px double #1d1d1d;
}
.clip h2 {
  margin: 0; font-family: Georgia, "Times New Roman", "Noto Serif", serif;
  font-size: 25px; font-weight: 700; line-height: 1.14; letter-spacing: -0.01em; text-wrap: balance;
}
.card.glance > p, .card.glance > .meta, .card.glance > .data { position: relative; z-index: 2; }
/* Marker-pen highlight: reads as emphasis at any weight, unlike bold inside bold. */
strong { font-weight: 750; background: linear-gradient(transparent 58%, var(--mark) 58%); }
/* The glance card's source line is the route to the article — the only one on
   a card whose detail tier failed verification. Padded to a thumb-sized target. */
.from {
  display: inline-flex; align-items: center; gap: 5px; align-self: start;
  color: var(--dim); font-size: 13px; padding: 10px 0;
  text-decoration: none;
}
.from .ico { width: 14px; height: 14px; }
.meta { display: flex; align-items: center; gap: 8px; margin-top: 8px; color: var(--dim); font-size: 13px; }
.meta .sep { opacity: .5; }
.readon { color: var(--link); font-size: 14px; margin-top: 26px; align-self: start; text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 2px; }
.kicker { color: var(--dim); font-size: 12px; text-transform: uppercase; letter-spacing: .1em; margin-bottom: 14px; }
.data { margin-top: 20px; border-top: 1px solid var(--line); font-size: 14px; }
.data div { display: flex; justify-content: space-between; gap: 16px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.data span:first-child { color: var(--dim); }

.ico { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* chrome — absolute against .phone */
.bar {
  position: absolute; inset: 0 0 auto 0; z-index: 3;
  display: flex; align-items: center; gap: 14px;
  padding: max(10px, env(safe-area-inset-top)) 20px 14px;
  font-size: 13px; color: var(--dim);
  background: linear-gradient(var(--bg) 66%, transparent);
  pointer-events: none;
}
.brand { font-size: 14px; font-weight: 750; letter-spacing: -0.01em; color: var(--fg); }
.bar button {
  display: inline-flex; align-items: center; gap: 6px; min-height: 36px;
  font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; pointer-events: auto;
}
.bar .ico { width: 16px; height: 16px; }
.pos { margin-left: auto; font-variant-numeric: tabular-nums; }
.dots { display: flex; gap: 6px; align-items: center; }
.dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--line); transition: background .18s; }
.dots i.on { background: var(--accent); }

/* Bottom-right: where a right thumb rests, and off the text column's width. */
.acts {
  position: absolute; inset: auto 0 0 0; z-index: 3;
  display: flex; gap: 8px; align-items: center;
  padding: 12px 20px max(18px, env(safe-area-inset-bottom));
  background: linear-gradient(transparent, var(--bg) 42%);
}
.acts button {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
  font: inherit; font-size: 13px; font-variant-numeric: tabular-nums; color: var(--fg);
  background: var(--sheet); border: 1px solid var(--line);
  border-radius: 999px; padding: 0 15px; cursor: pointer;
}
.acts button:disabled { opacity: .35; cursor: default; }
.hint { margin-right: auto; color: var(--dim); font-size: 12px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
::selection { background: var(--mark); }

.bar { transition: background .2s; }
.phone.on-glow .bar { background: none; } /* the glow runs under the header, not behind a band */

/* sheet — also absolute, so it rises inside the phone */
#sheet {
  position: absolute; inset: auto 0 0 0; z-index: 5;
  max-height: 82%; overflow-y: auto;
  background: var(--sheet); border-top: 1px solid var(--line);
  border-radius: 18px 18px 0 0;
  padding: 22px 24px max(24px, env(safe-area-inset-bottom));
  transform: translateY(101%); transition: transform .24s ease;
}
#sheet.open { transform: none; }
/* Never rely on the UA stylesheet alone: any author `display` on #sheet would
   silently beat [hidden] and leave the sheet permanently on screen. */
#sheet[hidden] { display: none !important; }
#scrim { position: absolute; inset: 0; z-index: 4; background: #000; opacity: 0; pointer-events: none; transition: opacity .24s; }
#scrim.open { opacity: .45; pointer-events: auto; }
#sheet h2 { margin: 0 0 14px; font-size: 14px; text-transform: uppercase; letter-spacing: .08em; color: var(--dim); }
/* The camps line is a summary, not a comment — it must not look like one. */
#sheet .camps { background: var(--tint); border-radius: 10px; padding: 13px 15px; margin-bottom: 4px; }
#sheet .camps-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--link); margin-bottom: 5px; }
#sheet .camps p { margin: 0; font-size: 14px; line-height: 1.55; }
#sheet .cmt { border-top: 1px solid var(--line); padding: 16px 0 6px; }
#sheet .cmt p { margin: 0; font-size: 14.5px; line-height: 1.62; }
#sheet .who { font-size: 12.5px; font-weight: 650; color: var(--dim); margin-bottom: 6px; }
#sheet .cmt a, #sheet dt a { color: var(--link); }
#sheet dl { margin: 0; }
#sheet dt { font-weight: 640; margin-top: 14px; }
#sheet dd { margin: 4px 0 0; color: var(--dim); }
#sheet .days { display: flex; flex-wrap: wrap; gap: 8px; }
#sheet .days a { border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; text-decoration: none; color: var(--fg); font-size: 14px; }
#sheet .days a.now { border-color: var(--accent); color: var(--link); }

.end { text-align: center; }
.end h1 { font-size: 25px; margin: 0 0 8px; }
.end p { color: var(--dim); margin: 0; }
.end .older { margin-top: 26px; font-size: 14px; opacity: .75; }
.empty { padding: 30px 22px; color: var(--dim); }
