/* =====================================================================
   site.css — the permanent world of the site (atmosphere, layout, type)
   Item-specific artwork lives in art.css. Keep the two separate:
   SITE = stable world · ITEM = content-specific artwork.
   ===================================================================== */

/* ---------- tokens (light version; a future dark theme overrides these) ---------- */
:root{
  --bg:#f0e8d6;          /* warm light ground (NEG2) */
  --ink:#0f0d18;
  --ink-2:#4a3e30;
  --ink-3:#6a5840;
  --ink-4:#74633f;      /* darkened slightly: must read on the deeper lower ground */
  --red:#c2615a;         /* dusty red atmosphere */
  --red-deep:#8a3230;
  --ochre:#c8920a;       /* mineral lower field */
  --ochre-deep:#6e4c04;
  --cyan:#38d4e8;        /* icy element */
  --cyan-deep:#08707f;
  --line:rgba(15,13,24,.14);
  /* The reading surface. Warm parchment rather than a white UI panel: the
     same family as --bg, a shade lighter, so the capsule reads as paper laid
     on the landscape instead of a card floating above it. Kept under ~9%
     saturation — any more and it turns yellow instead of warm. */
  --capsule:#f7f0e3;     /* reading capsule ground */
  --capsule-ink:#241f2c;  /* dark plum, a step softer than near-black */
  /* the reading scrim: one warm veil that pushes the landscape a plane back
     while the reader is inside an article (see body:has(article)::after).
     Tuned by actual on-screen appearance (29.08.2026): the original
     rgba(247,240,227,.10) blended too close to the landscape's own warm
     tones to read as a veil at all — side-by-side on/off comparisons in the
     live browser showed a ~3-11/255 shift, below the threshold of
     perception. A denser parchment tone at .16 alpha produces a clearly
     visible, still-subtle atmospheric separation without dimming or
     desaturating the scene underneath. */
  --scrim:rgba(250,236,205,.16);

  /* The type system (decided 29.08.2026):
     --head  IBM Plex Sans Hebrew — the author's name, headings, section
             names, and the article body itself. One reading voice.
     --sans  Heebo — the deck, navigation, and secondary text (the
             letterspaced register the eyebrows always had).
     --mono  Courier New where it exists (Windows/macOS); Cousine — its
             metric twin on Google Fonts, WITH Hebrew — covers Android and
             anything else. Chapter numbers, dates, metadata, technical
             Latin (Processing…, .zip). */
  --head:'IBM Plex Sans Hebrew',system-ui,-apple-system,'Segoe UI',Arial,sans-serif;
  --sans:'Heebo',system-ui,-apple-system,'Segoe UI',Arial,sans-serif;
  --mono:'Courier New','Cousine','Miriam Fixed',monospace;
  --serif:var(--head); /* legacy alias — everything that said serif now reads Plex */

  --measure:34rem;       /* comfortable Hebrew reading width */
  --gutter:clamp(18px,4vw,56px);
  --maxw:1180px;
  --next-align:left;      /* the "next" slot sits on the physical left in RTL */
  --dx:1;                /* +1 in RTL, -1 in LTR: flips the few physical x-offsets */
}
html[dir="ltr"]{--dx:-1;--next-align:right;}

/* ---------- reset ---------- */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;}
body{
  font-family:var(--sans);font-weight:300;color:var(--ink);
  background:var(--bg);line-height:1.5;min-height:100vh;
}
img{max-width:100%;display:block;}
a{color:inherit;}
ul{list-style:none;}
.skip{position:absolute;inset-inline-start:-999px;top:8px;background:var(--ink);color:var(--bg);padding:8px 14px;z-index:200;}
.skip:focus{inset-inline-start:8px;}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);}

/* ---------- SITE ATMOSPHERE ----------
   A stable landscape vista (NEG2 logic), FIXED to the viewport: red dusty
   sky above, a bright horizon band, the cyan ice mass sitting on the
   horizon, ochre mineral foreground below. It never scrolls away — sky,
   horizon and ice stay in view on every page, at every scroll position.

   On top of it, .depth is a document-height, mostly-transparent layer that
   very gradually adds foreground weight toward the end of long pages: the
   "slightly lowered gaze". Same scene throughout — no scene sequence. */
html{overflow-x:clip;}
body{position:relative;isolation:isolate;}
/* The scene is one finite field, 15vh taller than the viewport (overscan).
   --scroll-p (set by assets/js/atmos.js) slides it up by at most 15vh:
   top of page = a touch more sky, bottom = a touch more foreground.
   ~87%% of the scene stays common between the two extremes. */
.atmos{
  position:fixed;top:0;left:0;right:0;height:115vh;
  z-index:-2;overflow:hidden;background:var(--bg);pointer-events:none;
  transform:translate3d(0,calc(var(--scroll-p,0) * -15vh),0);
  will-change:transform;
}
.atmos > div{position:absolute;}

/* background plane: sky — strong dusty red, melting (not cut) into the light */
.atmos .sky{
  top:-60px;left:-60px;right:-60px;height:59vh;
  background:linear-gradient(180deg,
    #bd5d55 0%, #c2615a 18%, rgba(194,97,90,.72) 46%,
    rgba(207,124,104,.4) 68%, rgba(226,178,140,.16) 86%, rgba(240,232,214,0) 100%);
  filter:blur(14px);
  clip-path:polygon(0 0,100% 0,100% 78%,84% 90%,62% 82%,46% 94%,30% 86%,12% 96%,0 88%);
}
/* binary pair — two small distant stars suspended in dusty haze, not two
   coloured discs. Each is a very soft core plus a wide, much fainter bloom;
   low contrast, no hard edge, no neon. Red: larger and more diffused, ember
   behind dust. Blue: smaller and a touch crisper, near-white with a cool
   cast. Both sit in the upper 10% of the scene, so the existing scroll
   reframing carries them past the top edge. Never animated.

   ── WHERE THE PAIR SITS ──────────────────────────────────────────────────
   The two are placed as ONE system: a barycentre (--sun-x / --sun-y) plus a
   fixed offset each. assets/js/suns.js moves only the barycentre, along a
   shallow daily arc read from the browser's local clock, and may drift the
   offsets very slowly over days. Nothing about their appearance changes.

   The values below ARE the approved midday composition: with JavaScript off
   they resolve to exactly the positions this pair has always had
   (sun-a 5.1vh/66%, sun-b 7.4vh/70.8%), so the CSS alone is a complete,
   correct rendering and the script is an enhancement on top of it.

   --sun-arc is the horizontal half-travel in % of viewport width, and it
   lives here rather than in the script because it is a composition
   constraint: it is what keeps the pair clear of the masthead. */
:root{
  --sun-x:68.4%;    --sun-y:6.25vh;        /* barycentre — midday reference */
  --sun-ax:-2.4%;   --sun-ay:-1.15vh;      /* warm sun, up and to the left  */
  --sun-bx:2.4%;    --sun-by:1.15vh;       /* cool sun, down and to the right */
  --sun-arc:9;                             /* half-travel, % of viewport width */
}
@media (max-width:999px){ :root{ --sun-arc:6; } }
@media (max-width:699px){ :root{ --sun-arc:5; } }

.atmos .sun-a,.atmos .sun-b{border-radius:50%;aspect-ratio:1;}
.atmos .sun-a::after,.atmos .sun-b::after{ /* the atmospheric bloom */
  content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  border-radius:50%;aspect-ratio:1;pointer-events:none;
}
.atmos .sun-a{                             /* warm: ember behind dust */
  top:calc(var(--sun-y) + var(--sun-ay));
  left:calc(var(--sun-x) + var(--sun-ax));
  width:clamp(19px,1.9vw,29px);
  background:radial-gradient(circle at 50% 50%,
    rgba(240,176,148,.54) 0 38%, rgba(228,140,116,.24) 70%, rgba(226,136,112,0) 100%);
  filter:blur(4.2px);
}
.atmos .sun-a::after{
  width:340%;
  background:radial-gradient(circle at 50% 50%,
    rgba(226,136,110,.16) 0 22%, rgba(216,124,100,.06) 52%, rgba(214,120,98,0) 100%);
  filter:blur(9px);
}
.atmos .sun-b{                             /* cool: near-white, blue cast */
  top:calc(var(--sun-y) + var(--sun-by));
  left:calc(var(--sun-x) + var(--sun-bx));
  width:clamp(10px,1vw,15px);
  background:radial-gradient(circle at 50% 50%,
    rgba(226,242,248,.5) 0 42%, rgba(178,214,232,.22) 72%, rgba(178,214,232,0) 100%);
  filter:blur(2.4px);
}
.atmos .sun-b::after{
  width:300%;
  background:radial-gradient(circle at 50% 50%,
    rgba(174,210,230,.12) 0 24%, rgba(160,198,222,.045) 54%, rgba(160,198,222,0) 100%);
  filter:blur(7px);
}

/* the bright band at the horizon — light on water */
.atmos .glowband{
  top:47vh;left:0;right:0;height:14vh;
  background:radial-gradient(ellipse 85% 55% at 50% 50%, rgba(250,240,216,.9) 0%, rgba(250,240,216,0) 72%);
  filter:blur(10px);
}
/* midground: the implied icy mass — NEG2 language, restored literally.
   NEG2 draws it as ONE flat translucent cyan plane with a cut, irregular
   outline (.kit-neg2 .s3: a single rgba(56,212,232,.14) fill, a five-point
   clip-path, no gradient, no blur, no shadow). That is the whole idea:
   graphic, not volumetric. It must read as a mass, never as a lit object
   and never as a pond, so:
     - ONE value of cyan. No gradient → no implied light direction, no volume.
     - A cut polygon outline. No ellipse → not a lake.
     - No peak, no facet planes, no cast shadow.
     - Only a hair of blur, enough to belong to this grainy world; the edges
       stay cut rather than dissolving into atmosphere.
   It is placed so its lower third runs under .ground (which follows it in the
   DOM): the ochre paints across it, so the form sits INTO the foreground
   instead of floating on top of the page. Overlap, not shading. */
.atmos .ice{
  top:51.5vh;left:50%;transform:translateX(-50%);
  width:clamp(176px,26vw,320px);aspect-ratio:1.42;   /* NEG2's proportion, at any width */
  background:rgba(56,212,232,.16);          /* ONE value — NEG2's .s3 fill */
  clip-path:polygon(48% 0,100% 68%,72% 100%,22% 96%,0 52%);  /* NEG2's outline */
  filter:blur(.6px);
  /* ~1.4:1, NEG2's proportion. No ::after: NEG2's mass has no internal
     division, and any second plane inside the outline immediately reads as a
     fold or a facet. The only tonal variation across the form is what lies
     behind it — pale band above, ochre below. That is the whole model. */
}

/* narrow viewports: the form scales down with the width, so anchored by its
   top it would stop reaching the ochre. Drop it so the same share of it sits
   into the foreground as on a wide screen. */
@media (max-width:700px){ .atmos .ice{ top:55.5vh; } }

/* a second, far shard — keeps the mass from reading as a logo/object.
   Same flat fill + cut outline; a touch more blur only for distance, and
   quieter than before so the main mass stays the single subject. */
.atmos .ice2{
  top:52.5vh;left:15%;width:8vw;height:6vh;min-width:64px;
  background:rgba(56,212,232,.12);
  clip-path:polygon(30% 0,100% 34%,82% 100%,8% 84%,0 42%);
  filter:blur(2px);
}
/* foreground: ochre mineral mass — melting upward into the light band */
.atmos .ground{
  bottom:-60px;left:-60px;right:-60px;height:60vh;
  background:linear-gradient(0deg,
    #b8860c 0%, #c8920a 22%, rgba(200,146,10,.66) 50%,
    rgba(200,146,10,.30) 74%, rgba(200,146,10,0) 100%);
  filter:blur(14px);
  clip-path:polygon(0 16%,14% 6%,32% 14%,52% 4%,70% 12%,88% 2%,100% 10%,100% 100%,0 100%);
}
/* foreground formation — a cut crystalline / frozen-ocean mass at the very
   bottom of the scene, mostly below the viewport at the top of a page and
   progressively revealed as the framing lowers. Quiet, ambiguous, cut by the
   bottom edge: the near anchor of the suns → horizon+ice → foreground chain. */
.atmos .shelf{
  bottom:-2vh;left:-4%;right:-4%;height:20vh;
  background:linear-gradient(180deg,
    rgba(198,230,232,.34) 0%, rgba(146,192,200,.30) 42%, rgba(96,146,158,.32) 100%);
  clip-path:polygon(0 34%,9% 22%,17% 30%,28% 14%,38% 26%,47% 18%,
                    58% 31%,67% 21%,78% 33%,88% 24%,100% 36%,100% 100%,0 100%);
  filter:blur(3px);
}
.atmos .shelf::after{ /* a second, paler ridge — layered, not one clean edge */
  content:"";position:absolute;left:6%;right:10%;bottom:0;height:74%;
  background:linear-gradient(180deg, rgba(232,244,240,.26) 0%, rgba(232,244,240,0) 78%);
  clip-path:polygon(0 46%,12% 30%,24% 41%,36% 26%,49% 38%,62% 28%,74% 42%,86% 32%,100% 44%,100% 100%,0 100%);
  filter:blur(5px);
}

/* faint low shards near the bottom edge — foreground depth cue, under content areas' own grounds */
.atmos .fore{
  bottom:0;left:0;right:0;height:14vh;
  background:
    radial-gradient(ellipse 16% 90% at 22% 100%, rgba(110,76,4,.34) 0%, rgba(110,76,4,0) 70%),
    radial-gradient(ellipse 12% 70% at 74% 100%, rgba(8,112,127,.16) 0%, rgba(8,112,127,0) 70%),
    radial-gradient(ellipse 10% 60% at 58% 100%, rgba(138,50,48,.14) 0%, rgba(138,50,48,0) 70%);
  filter:blur(8px);
}
/* ---------- the drifter ----------
   The moving object itself is procedural (assets/js/object1.js) and renders
   on the .driftc canvas below. The .drifter element here is the STATIC
   fallback: it is what remains visible with prefers-reduced-motion or
   without JS — parked in the transition band, no autonomous movement.
   It must never carry an animation: MVP5 animated this element left-to-right
   and that is the motion we are getting rid of. object1.js removes the
   element outright once the canvas takes over. */
.atmos .drifter{
  top:20vh;left:60%;
  width:clamp(10px,1.1vw,16px);height:clamp(3px,.34vw,5px);
  opacity:.3;
}
.atmos .drifter i{
  position:absolute;inset:0;display:block;
  background:rgba(84,97,103,.8);           /* cool grey, slight cyan cast */
  clip-path:polygon(0 55%,44% 0,100% 26%,74% 100%,16% 86%);
  filter:blur(1.1px);mix-blend-mode:multiply;
}
.atmos .driftc{
  position:absolute;top:0;left:0;width:100%;height:115vh;
  filter:blur(.5px);                       /* distance; grain layers add the rest */
}
/* the shard cluster (assets/js/shards.js) — a nearer depth plane, so it sits
   above the horizon drifter's canvas but still under the grain layers. */
.atmos .shardc{
  position:absolute;top:0;left:0;width:100%;height:115vh;
  filter:blur(.7px);
}

.grain,.coarse{position:absolute;inset:0;pointer-events:none;}
.grain{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 300'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size:220px 220px;opacity:.5;mix-blend-mode:multiply;
}
.coarse{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400'%3E%3Cfilter id='c'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.18' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23c)'/%3E%3C/svg%3E");
  background-size:480px 480px;opacity:.18;mix-blend-mode:multiply;
}

/* the lowered gaze: document-height, transparent for the first viewport,
   then a gentle gain of mineral foreground weight. Max opacity stays low —
   the vista behind it must remain fully readable. */
.depth{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(184,134,12,0) 0%,
    rgba(184,134,12,0) 55%,
    rgba(166,118,26,.14) 80%,
    rgba(114,96,44,.18) 93%,
    rgba(52,92,96,.20) 100%);
}

/* ---------- the reading scrim ----------
   Only on article pages (the one place a reader stays for a thousand words):
   a single warm veil, fixed to the viewport, that sets the landscape one
   plane farther back so it stops competing with the text. It is NOT glass —
   no blur, no border, no panel. It sits at z-index -1, i.e. above .atmos and
   .depth but behind every piece of content, so artwork, navigation and the
   capsule are untouched; only the world behind them is quieted. The grain
   and the scene stay fully legible at this strength.
   :has() is the whole mechanism — a browser without it simply shows the
   unveiled background, which is the previous, perfectly good behaviour. */
body:has(article)::after{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:var(--scrim);
}

/* ---------- shell ---------- */
.wrap{max-width:var(--maxw);margin:0 auto;padding-inline:var(--gutter);}

.site-header{
  display:flex;align-items:baseline;justify-content:space-between;gap:24px;flex-wrap:wrap;
  padding:28px 0 22px;border-bottom:1px solid var(--line);
}
.brand{font-family:var(--head);font-weight:500;font-size:22px;letter-spacing:-.01em;text-decoration:none;color:var(--ink);}
.nav{display:flex;gap:26px;flex-wrap:wrap;}
.nav a{font-size:12px;letter-spacing:.2em;text-decoration:none;color:var(--ink-2);padding-bottom:4px;border-bottom:1px solid transparent;transition:color .2s,border-color .2s;}
.nav a:hover{color:var(--red-deep);}
.nav a[aria-current="page"]{color:var(--ink);border-bottom-color:var(--red-deep);}
/* language switch — only exists while the English side is live. The header-end
   box is a plain block everywhere else; it becomes a row only when it holds the
   switch, so pages without one are untouched. */
.header-end:has(.lang-switch){display:flex;align-items:baseline;gap:26px;flex-wrap:wrap;}
.header-end:has(.lang-switch) .account:empty{display:none;}
.lang-switch{font-size:12px;letter-spacing:.2em;text-decoration:none;color:var(--ink-3);padding-bottom:4px;border-bottom:1px solid transparent;padding-inline-start:26px;border-inline-start:1px solid var(--line);transition:color .2s;}
.lang-switch:hover,.lang-switch:focus-visible{color:var(--red-deep);}
/* English: no Hebrew-tuned justification rivers — hyphenate instead */
html[lang="en"] .prose p{hyphens:auto;}

main{padding-block:clamp(36px,6vh,72px) clamp(48px,8vh,96px);}

.site-footer{
  border-top:1px solid rgba(15,13,24,.22);padding:28px 0 48px;
  display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center;
}
.site-footer .nav{justify-content:center;}
.site-footer .nav a{color:var(--ink);}
.footer-meta{font-family:var(--mono);font-size:11px;letter-spacing:.02em;color:var(--ink);}
.footer-meta a{text-decoration:none;color:inherit;}
.footer-meta a:hover{color:var(--red-deep);}

/* Reusable: hides an element visually while a screen reader still announces
   it — used for the newsletter band's <label>, which the placeholder makes
   visually redundant but assistive tech still needs. */
.visually-hidden{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;
}

/* Text colours in the band and footer are --ink, not the quieter --ink-2/3/4
   used elsewhere: the ground behind them is the mid-tone ochre, where only
   --ink clears 4.5:1 (see the contrast measurements in the commit message).
   The newsletter band: no box. Like every other section it sits straight on
   the atmosphere, headed by .section-head and separated by hairlines only. */
.newsletter-band{margin-top:clamp(36px,6vh,72px);margin-bottom:72px;text-align:center;}
.newsletter-band .meta{justify-content:center;}
.newsletter-band .newsletter-consent{color:var(--ink);}
.newsletter-invite{font-size:clamp(20px,2.4vw,26px);margin-bottom:18px;}
.newsletter-form{width:fit-content;max-width:100%;margin-inline:auto;}
/* The form is as wide as the prominent line and nothing else: the row and the
   consent line take 100% of it (width:0 + min-width:100% keeps their own
   content out of the width calculation, so the consent line wraps instead). */
.newsletter-controls,.newsletter-consent{width:0;min-width:100%;}
.newsletter-consent{text-wrap:balance;}
.newsletter-controls{display:flex;align-items:stretch;gap:12px;}
.newsletter-controls input[type="email"]{
  flex:1;min-width:0;font-family:var(--mono);font-size:13px;color:var(--ink);
  background:transparent;border:0;border-bottom:.8px solid var(--ink-2);border-radius:0;
  padding:6px 0 6px 40px;text-align:center;
}
.newsletter-controls input[type="email"]::placeholder{font-family:var(--mono);color:var(--ink);opacity:1;}
.newsletter-controls button{
  font-family:var(--sans);font-weight:700;font-size:15px;letter-spacing:0;white-space:nowrap;
  color:var(--capsule);background:var(--red-deep);border:0;border-radius:2px;
  padding:6px 14px;cursor:pointer;transition:background-color .2s;
}
.newsletter-controls button:hover{background:var(--ink);}
.newsletter-controls input[type="email"]:focus-visible{outline:none;border-bottom:1.5px solid var(--ink);padding-bottom:5.3px;}
.newsletter-controls button:focus-visible{outline:1px solid var(--ink);outline-offset:3px;}
.newsletter-band .newsletter-msg{color:var(--ink);}
.newsletter-msg:empty{display:none;}
.newsletter-form[hidden]{display:none;}

/* ---------- shared type ---------- */
.eyebrow{font-size:10px;letter-spacing:.32em;text-transform:uppercase;color:var(--red-deep);margin-bottom:14px;}
.eyebrow.c-cyan{color:var(--cyan-deep);}
.eyebrow.c-ochre{color:var(--ochre-deep);}
.eyebrow.c-muted{color:var(--ink-4);}
h1,h2,h3{font-family:var(--head);font-weight:300;line-height:1.15;letter-spacing:-.01em;color:var(--ink);}
/* technical Latin inside titles (Processing…, ‎.zip) rides the mono voice */
h1 bdi,h1 [dir="ltr"],h2 bdi,h2 [dir="ltr"],h3 bdi,h3 [dir="ltr"]{font-family:var(--mono);font-size:.9em;letter-spacing:0;}
.deck{font-family:var(--sans);font-weight:300;font-size:clamp(16px,1.6vw,19px);line-height:1.65;color:var(--ink-2);max-width:46ch;}
.meta{font-family:var(--mono);font-size:11px;letter-spacing:.02em;color:var(--ink-4);display:flex;gap:16px;flex-wrap:wrap;margin-top:14px;}
.meta .hl{color:var(--ochre-deep);}
.rule{width:64px;height:1px;background:linear-gradient(90deg,transparent,var(--ink),transparent);opacity:.35;}

.section-head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin-bottom:22px;padding-bottom:10px;border-bottom:1px solid var(--line);}
.section-head h2{font-size:14px;font-family:var(--head);font-weight:500;letter-spacing:.26em;color:var(--ink-3);}
.section-head a{font-size:11px;letter-spacing:.16em;text-decoration:none;color:var(--ink-4);}
.section-head a:hover{color:var(--red-deep);}

/* placeholder marker — visible, unambiguous, removable */
.ph{display:inline-block;font-size:10px;letter-spacing:.2em;color:var(--ochre-deep);border:1px dashed currentColor;padding:3px 8px;border-radius:2px;vertical-align:middle;}

/* ---------- ITEM CONTAINER (information contract) ----------
   .item = art + type + title + deck + meta. Artwork varies per item. */
.item{display:grid;grid-template-columns:1fr;gap:16px;text-decoration:none;color:inherit;}
/* fixed size: .item repeats (the two-up standalone cards, the three-card
   standalone grid), so it gets the same fixed square as .chapter/
   .series-row, for the same reason — see .series-row .art. It stacks
   above its copy rather than sitting beside it, so it stays centred
   rather than pinned to an outer edge. */
.item .art{
  aspect-ratio:1/1;position:relative;overflow:hidden;border:1px solid var(--line);
  width:240px;height:auto;margin-inline:auto;
}
.item h3{font-size:clamp(20px,2.4vw,26px);margin-bottom:8px;transition:color .2s;}
.item:hover h3{color:var(--red-deep);}
.item .deck{font-size:15px;}
.item .meta{margin-top:10px;}

/* ---------- PAGE HERO (index/series/article entrances) ---------- */
.page-head{padding-bottom:clamp(28px,5vh,48px);margin-bottom:clamp(28px,5vh,48px);border-bottom:1px solid var(--line);}
.page-head h1{font-size:clamp(34px,5.6vw,60px);margin-bottom:16px;}
.page-head .deck{font-size:clamp(17px,1.8vw,21px);}

/* ================= HOMEPAGE ================= */
.feature{
  display:grid;grid-template-columns:1.25fr 1fr;gap:clamp(20px,4vw,56px);align-items:center;
  padding-bottom:clamp(36px,6vh,64px);margin-bottom:clamp(36px,6vh,64px);border-bottom:1px solid var(--line);
}
/* .feature is a two-column row (art beside copy) — the square tracks the
   copy's height instead of the column's width, and stays pinned to the row's
   outer edge (art is the first, wider column here — its own inline-start
   edge is already the layout's outer edge in RTL, hence justify-self:start). */
.feature .art{
  aspect-ratio:1/1;position:relative;overflow:hidden;border:1px solid var(--line);
  align-self:stretch;height:100%;width:auto;max-height:22rem;min-height:11rem;
  justify-self:start;
}
.feature h1{font-size:clamp(34px,5vw,58px);margin-bottom:18px;}
.feature h1 a{text-decoration:none;}
.feature h1 a:hover{color:var(--red-deep);}

.home-grid{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);gap:clamp(28px,5vw,72px);align-items:start;}
.stream > section + section{margin-top:clamp(40px,6vh,64px);}

/* series card on the homepage: wide art + copy */
.series-card{display:grid;grid-template-columns:1fr 1.1fr;gap:clamp(16px,3vw,36px);align-items:center;text-decoration:none;color:inherit;}
.series-card .art{aspect-ratio:1/1;}
.series-card h3{font-size:clamp(26px,3vw,36px);}
.series-card .count{display:flex;gap:6px;align-items:center;margin-top:16px;font-family:var(--mono);font-size:11px;letter-spacing:.04em;color:var(--ink-4);}

.two-up{display:grid;grid-template-columns:1fr 1fr;gap:clamp(18px,3vw,36px);}

/* sidebar: שוליים — lighter, smaller */
.side-notes .note{padding:16px 0;border-bottom:1px solid var(--line);}
.side-notes .note:first-of-type{padding-top:0;}
.note time{display:block;font-family:var(--mono);font-size:10px;letter-spacing:.06em;color:var(--ink-4);margin-bottom:6px;}
.note p{font-family:var(--sans);font-weight:300;font-size:15px;line-height:1.6;color:var(--ink-2);}
.side-block + .side-block{margin-top:clamp(36px,5vh,56px);}
.side-block .mini{display:block;text-decoration:none;color:inherit;padding:14px 0;border-bottom:1px solid var(--line);}
.side-block .mini strong{display:block;font-family:var(--serif);font-weight:400;font-size:17px;margin-bottom:4px;}
.side-block .mini span{font-size:13px;color:var(--ink-3);}
.side-block .mini:hover strong{color:var(--red-deep);}

/* ================= SERIES INDEX ================= */
.series-list{display:grid;gap:clamp(32px,5vh,56px);}
.series-row{display:grid;grid-template-columns:1fr 1.4fr;gap:clamp(20px,4vw,56px);align-items:center;text-decoration:none;color:inherit;}
/* fixed size, not text-driven: this repeats down a list of seven, and a
   size that tracked each row's own copy length produced a visibly uneven
   column (204-268px) that read as "why is this one bigger" rather than as
   a consistent set of plates. Art first/wider column (right, in RTL). */
.series-row .art{
  aspect-ratio:1/1;position:relative;overflow:hidden;border:1px solid var(--line);
  width:240px;height:auto;
  justify-self:start;
}
.series-row h2{font-size:clamp(30px,4vw,46px);margin-bottom:14px;transition:color .2s;}
.series-row:hover h2{color:var(--red-deep);}
.series-slot{border:1px dashed var(--line);padding:28px;color:var(--ink-4);font-size:12px;letter-spacing:.14em;text-align:center;}

/* ================= SERIES PAGE ================= */
.series-hero{display:grid;grid-template-columns:1fr 1fr;gap:clamp(20px,4vw,56px);align-items:end;}
/* here the copy comes first in markup and the art second, so art lands in
   the second column (left, in RTL) — its outer edge is that column's
   inline-end, hence justify-self:end (opposite of .feature/.series-row). */
.series-hero .art{
  aspect-ratio:1/1;position:relative;overflow:hidden;border:1px solid var(--line);
  align-self:stretch;height:100%;width:auto;max-height:22rem;min-height:11rem;
  justify-self:end;
}
.series-hero h1{font-size:clamp(40px,6.4vw,72px);}
/* ---------- series navigation (the DNA strip, now clickable) ----------
   The visual language is unchanged: 18x2px marks — solid = published,
   half/ochre = announced, faint = not yet written. What changed is that a
   published mark is now a real <a> to its article. Each mark sits in a
   positioned .dna-mark wrapper: ::before stretches an invisible ~24x44px
   hit area around the tiny mark (the visible layout stays identical), and
   ::after carries a small hover/focus label in the site's metadata voice.
   Announced marks are inert spans — focusable for screen readers, never
   links. Reusable for any series: markup comes from series_nav() in
   _build.py. */
.series-dna{display:flex;gap:6px;align-items:center;margin:18px 0 0;}
.series-dna .dna-mark{position:relative;display:block;}
.series-dna .dna-mark i{display:block;width:18px;height:2px;background:var(--ink);opacity:.18;transition:opacity .2s,background .2s;}
.series-dna .dna-mark.on i{opacity:.9;}
.series-dna .dna-mark.up i{opacity:.45;background:var(--ochre-deep);}
.series-dna .dna-mark::before{content:"";position:absolute;inset:-21px -3px;}   /* hit area */
.series-dna span.dna-mark{cursor:default;}
.series-dna a.dna-mark:hover i,
.series-dna a.dna-mark:focus-visible i{opacity:1;background:var(--red-deep);}
.series-dna .dna-mark:focus-visible{outline:none;}
.series-dna .dna-mark:focus-visible i{outline:1px solid var(--red-deep);outline-offset:5px;}
.series-dna .dna-count{font-family:var(--mono);font-size:10px;letter-spacing:.06em;color:var(--ink-4);margin-inline-start:10px;}
/* the label. Positioning is written for this RTL document: inset-inline-start
   resolves to `right`, so right:50% + translateX(50%) centers it over the
   mark; the first (inline-start-most) mark anchors to its start edge instead
   so the label grows into the page, never past the viewport edge. */
.series-dna .dna-mark::after{
  content:attr(data-tip);
  position:absolute;bottom:calc(100% + 12px);inset-inline-start:50%;
  transform:translateX(calc(50% * var(--dx))) translateY(3px);
  font-family:var(--mono);font-size:10px;letter-spacing:.06em;color:var(--ink-2);
  background:var(--bg);border:1px solid var(--line);padding:5px 10px;white-space:nowrap;
  opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;z-index:6;
}
.series-dna .dna-mark:hover::after,
.series-dna .dna-mark:focus-visible::after{opacity:1;transform:translateX(calc(50% * var(--dx))) translateY(0);}
.series-dna .dna-mark:first-child::after{inset-inline-start:-3px;transform:translateY(3px);}
.series-dna .dna-mark:first-child:hover::after,
.series-dna .dna-mark:first-child:focus-visible::after{transform:translateY(0);}
/* touch: no hover — a tap on a published mark simply navigates, and the
   aria-labels carry the titles; suppress the labels so nothing can overflow
   a small viewport. */
@media (hover:none){.series-dna .dna-mark::after{display:none;}}

.chapters{display:grid;gap:clamp(36px,6vh,72px);}
.chapter{display:grid;grid-template-columns:1.15fr 1fr;gap:clamp(20px,4vw,56px);align-items:center;text-decoration:none;color:inherit;}
.chapter:nth-child(even){grid-template-columns:1fr 1.15fr;}
.chapter:nth-child(even) .art{order:2;justify-self:end;}
/* fixed size, not text-driven — see .series-row .art above for why: seven
   of these in a column, and a size that tracked each row's own copy length
   read as uneven blocks rather than a consistent set of plates.
   Odd chapters: art is the first, wider (1.15fr) column (right, in RTL).
   Even chapters swap the column widths AND push art after copy via
   order:2 above, which also flips which edge is "outer" — that rule
   carries its own justify-self:end. */
.chapter .art{
  aspect-ratio:1/1;position:relative;overflow:hidden;border:1px solid var(--line);
  width:240px;height:auto;
  justify-self:start;
}
.chapter .num{font-family:var(--mono);font-size:13px;letter-spacing:.12em;color:var(--ink-4);margin-bottom:12px;}
.chapter .num b{font-weight:400;color:var(--ink);font-size:20px;letter-spacing:0;margin-inline-end:10px;}
.chapter h2{font-size:clamp(28px,3.6vw,44px);margin-bottom:14px;transition:color .2s;}
.chapter:hover h2{color:var(--red-deep);}
.chapter.soon{opacity:.55;pointer-events:none;}

/* ---------- announced-but-unpublished items ("upcoming") ----------
   The card is a promise, not a door: it renders everywhere its published
   siblings do, visually held back (washed out, slightly desaturated), with
   no link. Hovering or focusing it raises it a little and shows the short
   explanation (data-note) — the note lives on the hover, never printed on
   the card itself. */
.locked{cursor:default;position:relative;}
.chapter.locked,.mini.locked,.series-row.locked{opacity:.5;filter:saturate(.35);transition:opacity .25s,filter .25s;}
.chapter.locked:hover,.chapter.locked:focus-visible,
.mini.locked:hover,.mini.locked:focus-visible,
.series-row.locked:hover,.series-row.locked:focus-visible{opacity:.72;filter:saturate(.6);outline:none;}
.locked::after{
  content:attr(data-note);
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) translateY(6px);
  background:var(--ink);color:var(--bg);
  font-family:var(--sans);font-weight:300;font-size:12px;letter-spacing:.14em;
  padding:9px 16px;border-radius:2px;white-space:nowrap;
  opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;z-index:5;
}
.locked:hover::after,.locked:focus-visible::after{
  opacity:1;transform:translate(-50%,-50%) translateY(0);
}
.mini.locked{display:block;padding:14px 0;border-bottom:1px solid var(--line);}
.mini.locked strong{display:block;font-family:var(--serif);font-weight:400;font-size:17px;margin-bottom:4px;}
.mini.locked span{font-size:13px;color:var(--ink-3);}

/* ================= ARTICLE ================= */
/* preview flag — a private, pre-publication copy of an article. Quiet by
   design (the site's metadata voice, one ochre rule), but present, so a
   reader always knows what they were sent and why they can't find it on the
   site. It survives printing on purpose: a printed preview stays marked. */
.preview-flag{
  display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
  border-top:2px solid var(--ochre-deep);
  padding:10px 0 12px;margin-bottom:clamp(26px,4vh,44px);
  font-family:var(--mono);font-size:11px;letter-spacing:.08em;color:var(--ink-4);
}
.preview-flag b{font-weight:700;color:var(--ochre-deep);letter-spacing:.18em;}

.article-hero{display:grid;grid-template-columns:1fr;gap:clamp(20px,4vh,36px);margin-bottom:clamp(40px,7vh,80px);}
.article-hero .art{
  /* width:100% gives the box a definite dimension to compute the other from —
     every .art child is position:absolute (art.css), so without one, width
     and height both stay auto and the box collapses to its border. */
  aspect-ratio:1/1;width:100%;max-width:24rem;margin-inline:auto;
  position:relative;overflow:hidden;border:1px solid var(--line);
}
.article-hero .copy{max-width:60rem;}
.article-hero .series-link{text-decoration:none;color:var(--red-deep);font-size:10px;letter-spacing:.32em;text-transform:uppercase;}
.article-hero .series-link:hover{color:var(--ink);}
/* The title keeps its RTL start alignment — it is the reading axis, and the
   editorial register depends on it. What it gains here is air: more room
   above and below, so the headline sits as a substantial block rather than
   being crowded by the metadata line and the standfirst. Spacing only. */
.article-hero .num{font-family:var(--mono);font-size:14px;letter-spacing:.1em;color:var(--ink-4);margin:20px 0 18px;}
.article-hero h1{font-size:clamp(38px,6.4vw,76px);line-height:1.12;margin-bottom:28px;}
/* the deck as a real standfirst (newspaper-style): noticeably larger than
   body text, still lighter than the headline — it is the article's second
   sentence, not a caption. */
.article-hero .deck{font-size:clamp(20px,2.3vw,27px);line-height:1.6;max-width:44ch;color:var(--ink-2);}

/* ---------- article utilities: back / share / print ----------
   Deliberately below the metadata line and deliberately quiet — these are
   tools, not calls to action, so they borrow the site's system voice (mono,
   small, letterspaced) instead of becoming buttons. No fill, no icon set:
   a hairline underline that warms to red on hover is the whole treatment,
   and <a> vs <button> carries the difference between navigating and acting.
   The row wraps on its own and every control clears a 44px tap target via
   vertical padding, so nothing needs a mobile-specific layout. */
.art-utils{
  display:flex;flex-wrap:wrap;align-items:center;gap:4px 26px;
  margin-top:22px;padding-top:16px;border-top:1px solid var(--line);
}
.art-utils .util{
  font-family:var(--mono);font-size:11px;letter-spacing:.1em;
  color:var(--ink-3);background:none;border:0;border-bottom:1px solid transparent;
  padding:11px 0;cursor:pointer;text-decoration:none;
  display:inline-flex;align-items:center;gap:8px;
  transition:color .2s,border-color .2s;
}
.art-utils .util:hover,
.art-utils .util:focus-visible{color:var(--red-deep);border-bottom-color:var(--red-deep);outline:none;}
.art-utils .util .ico{font-size:13px;line-height:1;opacity:.65;transition:transform .2s,opacity .2s;}
/* the glyph is chosen per language (→ in RTL, ← in LTR) so it always points "back"; --dx flips the travel */
.art-utils .util:hover .ico{opacity:1;transform:translateX(calc(3px * var(--dx)));}
/* the forward glyph (next article) travels the other way */
.art-utils .util[rel="next"]:hover .ico{transform:translateX(calc(-3px * var(--dx)));}
/* the share button reports its own result in its label — no toast to place,
   dismiss, or trap focus in. Red marks the moment, then it reverts. */
.art-utils .util.done{color:var(--red-deep);border-bottom-color:var(--red-deep);}

/* optional content photo (article or series) — deliberately plain: it
   illustrates the piece, it isn't part of the drawn "art" visual language,
   so it gets no border/treatment tying it to that system. */
.content-image{max-width:calc(var(--measure) + 2*clamp(22px,5vw,64px));margin:0 auto clamp(28px,5vh,52px);}
.content-image img{width:100%;height:auto;display:block;border-radius:3px;}

/* a real image sitting in a card's art slot: sits in the same frame the
   drawn art does, so cards with and without photos stay aligned — but the
   frame no longer dictates the image's shape. See below for why. */
/* These artworks are never cropped - the bar near the top edge and the
   mass in the middle are a single composition, and cover-fit cuts the
   bar off. contain-fit shows the whole square; the cream matches the
   artwork's own paper so the leftover space reads as margin. */
.art-photo img{
  width:100%;height:100%;object-fit:contain;display:block;
  background:#f0e8d6;
}

/* reading capsule — a quieter container inside the world */
.capsule{
  background:var(--capsule);color:var(--capsule-ink);
  max-width:calc(var(--measure) + 2*clamp(22px,5vw,64px));
  margin:0 auto;padding:clamp(36px,6vh,72px) clamp(22px,5vw,64px);
  border:1px solid rgba(15,13,24,.09);
  /* the inset highlight is warmed to match the parchment — a pure-white
     hairline reads cold against it and reintroduces the "UI card" feel */
  box-shadow:0 1px 0 rgba(255,252,244,.7) inset,0 24px 60px -30px rgba(60,30,20,.32);
  position:relative;
}
.capsule::before{ /* faint top notch = doorway into the capsule */
  content:"";position:absolute;top:-1px;left:50%;transform:translateX(-50%);
  width:64px;height:1px;background:var(--red-deep);opacity:.6;
}
/* ---------- Plex in its reading register ----------
   Same family as the interface, deliberately a different voice inside the
   capsule: the UI keeps Plex at 400-500 in short bursts, the essay drops to
   300 over long paragraphs, where the lighter stroke stops the column of
   Hebrew from turning into a grey slab. Subheadings climb to 500/600 so the
   contrast between "reading" and "structure" does the work that a second
   typeface would otherwise do. Measure is unchanged — the column stays
   narrow on purpose, whatever room the capsule has. */
.prose{font-family:var(--head);font-weight:300;font-size:clamp(17.5px,1.33rem,20.5px);line-height:1.88;letter-spacing:.002em;}
.prose p{margin-bottom:1.4em;max-width:var(--measure);text-align:justify;}
.prose p:last-child{margin-bottom:0;}
.prose h2{font-size:1.32em;margin:2.15em 0 .75em;font-weight:600;line-height:1.3;letter-spacing:-.005em;}
.prose h3{font-size:1.12em;margin:2em 0 .65em;font-weight:500;line-height:1.35;}
.prose strong{font-weight:500;}
.prose em{font-style:italic;}

/* pull quote — a passage from the text, repeated as a graphic beat between
   paragraphs (the Haaretz pattern). Authored as a Markdown blockquote (>)
   inside the article body. One style for every length: red side bar,
   start-aligned, bold red text. (build adds class="long" to longer ones;
   it carries no separate styling.) */
.prose blockquote{
  margin:2.4em 0;padding:.25em 1.3em .35em;
  border-inline-start:3px solid var(--red-deep);
  text-align:start;
}
.prose blockquote p{
  margin:0;max-width:var(--measure);text-align:inherit;
  font-size:1.3em;line-height:1.5;font-weight:600;color:var(--red-deep);
}
/* the opening drop cap — the one place Solaris red enters the reading
   surface. Unchanged in size and role; it only gets a weight of its own so
   it still holds against the lighter 300 body around it, and a touch more
   optical margin now that the lines are more open. Opening paragraph only:
   .lede is applied to the first <p> and nowhere else. */
.prose .lede::first-letter{
  font-size:2.6em;line-height:.86;font-weight:400;
  float:inline-start;margin-inline-end:.12em;margin-top:.1em;
  color:var(--red-deep);
}
.prose .note-box{ /* clearly-marked placeholder body */
  font-family:var(--sans);font-size:13px;line-height:1.6;color:var(--ink-3);
  border:1px dashed var(--ochre-deep);padding:14px 18px;margin:2.2em 0 0;
}
.prose .note-box b{font-weight:400;color:var(--ochre-deep);letter-spacing:.16em;font-size:11px;display:block;margin-bottom:6px;}

/* ---------- end-of-article continuation ----------
   Where the reader lands after the last line: the direction word is a small
   system label, the chapter is the thing worth reading, and a hairline above
   each slot is the only divider. Plain page navigation — no arrow buttons,
   no carousel. The two slots share one rule set whether they are links or
   inert (announced-but-unpublished) so the row never changes shape. */
.article-nav{
  max-width:calc(var(--measure) + 2*clamp(22px,5vw,64px));
  margin:clamp(44px,7vh,76px) auto 0;
  display:grid;grid-template-columns:1fr 1fr;gap:16px clamp(20px,4vw,48px);
}
.article-nav a,.article-nav span.prev,.article-nav span.next{
  display:block;text-decoration:none;color:inherit;
  padding:20px 0 4px;border-top:1px solid var(--line);
}
.article-nav a span,
.article-nav span.prev > span,.article-nav span.next > span{
  display:block;font-family:var(--mono);font-size:10px;letter-spacing:.24em;
  color:var(--ink-4);margin-bottom:10px;
}
.article-nav a strong,
.article-nav span.prev strong,.article-nav span.next strong{
  display:block;font-family:var(--head);font-weight:400;
  font-size:clamp(17px,1.5vw,20px);line-height:1.35;
}
.article-nav a:hover strong,.article-nav a:focus-visible strong{color:var(--red-deep);}
/* physical on purpose: `end` would be re-resolved to the wrong side inside the dir="ltr" mono islands of a title */
.article-nav .next{text-align:var(--next-align);}
.article-nav a.disabled{opacity:.45;pointer-events:none;}
/* a neighbouring chapter that exists as an announcement only: same slot,
   same shape, no link — held back and explained on hover (.locked). */
.article-nav span.prev,.article-nav span.next{opacity:.5;}

/* ================= STANDALONE INDEX ================= */
.standalone-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(20px,3vw,40px);}

/* ================= שוליים ================= */
.margins{max-width:46rem;}
.margins .entry{display:grid;grid-template-columns:110px 1fr;gap:20px;padding:26px 0;border-bottom:1px solid var(--line);}
.margins .entry time{font-family:var(--mono);font-size:11px;letter-spacing:.04em;color:var(--ink-4);padding-top:6px;}
.margins .entry p{font-family:var(--serif);font-size:18px;line-height:1.7;color:var(--ink-2);}
.margins .entry .tag{display:inline-block;font-size:10px;letter-spacing:.22em;color:var(--cyan-deep);margin-bottom:8px;}

/* ================= ABOUT ================= */
.about{max-width:var(--measure);}
/* Photo sits in the page-head next to the name, not floated inside the
   body copy - the earlier float only wrapped the first two paragraphs and
   then quit, and it had nowhere to go on a narrow screen without shrinking
   the portrait to a favicon. This scales with the page instead. */
.about-head{display:flex;align-items:center;gap:28px;}
.about-head h1{margin-bottom:0;}
.about-photo{
  width:130px;
  height:130px;
  object-fit:cover;
  /* the source crop (660x770) already centers the face on x; going square
     crops roughly equal slices off top and bottom by default - biasing
     toward the top keeps headroom and trims shoulder instead of hair. */
  object-position:center 30%;
  border-radius:3px;
  flex-shrink:0;
}
.about p{font-family:var(--serif);font-size:19px;line-height:1.75;color:var(--ink-2);margin-bottom:1.2em;}

/* ================= הערות · article notes =================
   The social layer, and it is meant to read as marginalia rather than as a
   feed: no cards, no bubbles, no counters worth gaming. Hierarchy is made
   of spacing, one hairline, and the same three-voice type system as the
   rest of the site — display name in Plex, everything administrative
   (handle, time, actions) in the small mono register the utilities use.
   It sits OUTSIDE the capsule, on the landscape, like the continuation
   nav above it: the essay is finished paper, this is the desk around it. */
.notes{
  max-width:calc(var(--measure) + 2*clamp(22px,5vw,64px));
  margin:clamp(76px,13vh,140px) auto 0;   /* the deliberate silence after Prev/Next */
}
.notes-head{
  display:flex;align-items:baseline;gap:10px;
  padding-top:18px;border-top:1px solid var(--line);
  margin-bottom:clamp(20px,3vh,30px);
}
.notes-head h2{
  font-family:var(--head);font-weight:500;
  font-size:clamp(15px,1.25vw,17px);letter-spacing:.01em;color:var(--ink-2);
}
/* the count is metadata, not a score: mono, small, muted, never emphasised */
.notes-count{font-family:var(--mono);font-size:11px;letter-spacing:.12em;color:var(--ink-4);}

.notes-empty{
  font-family:var(--head);font-weight:300;font-size:16px;line-height:1.75;
  color:var(--ink-3);max-width:30rem;
}

/* ---- one note ---- */
.note-thread + .note-thread{border-top:1px solid rgba(15,13,24,.08);}
.note{padding:20px 0 18px;}
.note-head{display:flex;align-items:center;flex-wrap:wrap;gap:2px 10px;margin-bottom:8px;}
/* an initial in a hairline ring — presence without a colourful avatar */
.note-avatar{
  flex:none;width:26px;height:26px;border-radius:50%;
  border:1px solid var(--line);display:grid;place-items:center;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.02em;
  line-height:1;color:var(--ink-3);
}
.note-name{font-family:var(--head);font-weight:500;font-size:14.5px;color:var(--ink);}
.note-handle,.note-time{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.05em;color:var(--ink-4);
}
/* a Latin handle inside an RTL line: isolate it so punctuation can't jump,
   and let it break rather than push the row into a horizontal scroll */
.note-handle{direction:ltr;unicode-bidi:isolate;min-width:0;overflow-wrap:anywhere;}
.note-body{
  font-family:var(--head);font-weight:300;
  font-size:16.5px;line-height:1.78;color:var(--ink-2);
  white-space:pre-wrap;overflow-wrap:anywhere;
}
/* a mention is a quieter cousin of a link: the cool accent, nothing else.
   No pill, no fill, no glow — it must not out-shout the sentence holding it. */
/* direction, not just isolation: a bare `isolate` inherits the paragraph's
   RTL base, which throws the neutral "@" to the far side and renders the
   handle as "demo-a@". The run has to be explicitly LTR. */
.note-mention{color:var(--cyan-deep);direction:ltr;unicode-bidi:isolate;}
.note-reply{
  margin-top:9px;font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;
  color:var(--ink-4);background:none;border:0;border-bottom:1px solid transparent;
  padding:7px 0;cursor:pointer;transition:color .2s,border-color .2s;
}
/* hover gets the hairline; keyboard focus gets the ring from the shared
   rule below — never `outline:none` on a control a keyboard has to find. */
.note-reply:hover{color:var(--red-deep);border-bottom-color:var(--red-deep);}

/* ---- threading: two indents, then it stops ----
   A thin guide line does the work a nesting box would do, and because the
   script flattens anything past the second level the column can never
   shrink into a staircase on a narrow screen. */
.note-children{
  padding-inline-start:clamp(15px,3.2vw,26px);
  border-inline-start:1px solid rgba(15,13,24,.10);
}
.note-children .note{padding-top:16px;}

/* ---- composer ---- */
.notes-composer{
  position:relative;                       /* anchors the mention menu */
  margin-top:clamp(24px,4vh,38px);padding-top:20px;border-top:1px solid var(--line);
}
.notes-composer textarea{
  width:100%;min-height:92px;resize:vertical;display:block;
  font-family:var(--head);font-weight:300;font-size:16px;line-height:1.7;
  color:var(--capsule-ink);background:var(--capsule);
  border:1px solid var(--line);border-radius:2px;padding:13px 15px;
}
.notes-composer textarea::placeholder{color:var(--ink-4);opacity:1;}
/* one visible focus ring for every control in the notes layer */
.notes-composer textarea:focus-visible,
.notes-gate-btn:focus-visible,.composer-submit:focus-visible,
.reply-cancel:focus-visible,.account-btn:focus-visible,
.note-reply:focus-visible,.mention-item:focus-visible,
.notes-demo-btn:focus-visible,.auth-dialog :focus-visible{
  outline:2px solid var(--cyan-deep);outline-offset:2px;
}
.composer-actions{
  display:flex;align-items:center;justify-content:space-between;
  flex-wrap:wrap;gap:10px 18px;margin-top:12px;
}
.composer-hint{font-family:var(--mono);font-size:10px;letter-spacing:.1em;color:var(--ink-4);}
.composer-submit{
  font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--ink-2);
  background:none;border:1px solid var(--line);border-radius:2px;
  padding:10px 20px;min-height:40px;cursor:pointer;transition:color .2s,border-color .2s;
}
.composer-submit:hover{color:var(--red-deep);border-color:var(--red-deep);}

/* replying happens in the composer that is already there — this line is the
   only thing that changes, so the reader never loses their place */
.reply-context{
  display:flex;align-items:center;flex-wrap:wrap;gap:6px 14px;margin-bottom:11px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--ink-4);
}
.reply-context-label{display:inline-flex;align-items:center;gap:5px;}
.reply-cancel{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;color:var(--ink-4);
  background:none;border:0;border-bottom:1px solid var(--line);
  padding:4px 0;cursor:pointer;
}
.reply-cancel:hover{color:var(--red-deep);border-bottom-color:var(--red-deep);}

/* ---- @mention autocomplete ---- */
.mention-menu{
  /* `top` is set by script from the textarea's own offset, so the menu sits
     under the field whether or not the reply-context line is present. The
     max-width keeps it inside the viewport on a phone without any
     measuring — the composer is already inside the gutters. */
  position:absolute;z-index:40;inset-inline-start:0;top:0;
  min-width:170px;max-width:min(300px,calc(100vw - 2*var(--gutter)));
  max-height:186px;overflow-y:auto;
  background:var(--capsule);border:1px solid var(--line);border-radius:2px;
  box-shadow:0 5px 16px rgba(15,13,24,.09);
}
.mention-item{
  display:flex;align-items:baseline;gap:10px;
  padding:9px 13px;cursor:pointer;min-height:38px;
}
.mention-item + .mention-item{border-top:1px solid rgba(15,13,24,.06);}
.mention-item.on{background:rgba(8,112,127,.07);}
.mention-handle{font-family:var(--mono);font-size:11.5px;color:var(--cyan-deep);}
.mention-name{font-family:var(--head);font-weight:300;font-size:12.5px;color:var(--ink-3);}

/* ---- logged-out gate. Reading was never blocked; this only appears where
        the composer would have been, and only asks when asked of. ---- */
.notes-gate{
  margin-top:clamp(24px,4vh,38px);padding-top:20px;border-top:1px solid var(--line);
}
.notes-gate-text{font-family:var(--head);font-weight:300;font-size:15.5px;color:var(--ink-3);}
.notes-gate-actions{display:flex;flex-wrap:wrap;gap:0 24px;margin-top:6px;}
.notes-gate-btn{
  font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--ink-2);
  background:none;border:0;border-bottom:1px solid var(--line);
  padding:10px 0;min-height:40px;cursor:pointer;transition:color .2s,border-color .2s;
}
.notes-gate-btn:hover{color:var(--red-deep);border-bottom-color:var(--red-deep);}

/* ---- demo harness: only ever rendered under ?forum-demo=1 ---- */
.notes-demo{
  display:flex;align-items:center;flex-wrap:wrap;gap:8px 14px;
  margin-bottom:22px;padding:10px 14px;
  border:1px dashed rgba(8,112,127,.45);border-radius:2px;
  background:rgba(8,112,127,.04);
}
.notes-demo-tag{font-family:var(--mono);font-size:10px;letter-spacing:.2em;color:var(--cyan-deep);}
.notes-demo-text{font-family:var(--sans);font-size:12px;color:var(--ink-3);}
.notes-demo-btn{
  margin-inline-start:auto;font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;
  color:var(--ink-2);background:none;border:1px solid var(--line);border-radius:2px;
  padding:7px 12px;min-height:34px;cursor:pointer;
}
.notes-demo-btn:hover{color:var(--red-deep);border-color:var(--red-deep);}

/* ---- header account entry ----
   The slot is empty in the HTML and filled by script, so with JS off the
   masthead is exactly what it was. The divider only exists once something
   is in it. */
.header-end{display:flex;align-items:baseline;flex-wrap:wrap;gap:12px 26px;}
.account{display:flex;align-items:baseline;gap:14px;}
.account:not(:empty){padding-inline-start:26px;border-inline-start:1px solid var(--line);}
.account-btn{
  font-family:var(--sans);font-size:12px;letter-spacing:.2em;color:var(--ink-2);
  background:none;border:0;border-bottom:1px solid transparent;
  padding-bottom:4px;cursor:pointer;transition:color .2s,border-color .2s;
}
.account-btn:hover{color:var(--red-deep);}
.account-me{font-family:var(--mono);font-size:11px;letter-spacing:.04em;color:var(--ink-4);}

/* ---- auth prototype ---- */
.auth-dialog{
  /* inset+margin rather than the UA default: the browser's own modal
     positioning only pins the block axis, which in RTL leaves the box
     flush against one edge instead of centred. */
  inset:0;margin:auto;
  width:min(400px,calc(100vw - 28px));max-height:calc(100vh - 28px);
  overflow-y:auto;padding:0;
  border:1px solid var(--line);border-radius:3px;
  background:var(--capsule);color:var(--capsule-ink);
  box-shadow:0 18px 48px rgba(15,13,24,.20);
}
.auth-dialog::backdrop{background:rgba(15,13,24,.42);}
.auth-form{padding:22px 24px 20px;}
.auth-head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;}
.auth-head h2{font-family:var(--head);font-weight:500;font-size:18px;color:var(--capsule-ink);}
.auth-x{
  font-family:var(--head);font-size:22px;line-height:1;color:var(--ink-3);
  background:none;border:0;cursor:pointer;padding:4px 6px;
}
.auth-x:hover{color:var(--red-deep);}
.auth-note{
  margin-top:14px;font-family:var(--sans);font-size:12.5px;line-height:1.6;
  color:var(--red-deep);
}
.auth-fields{margin-top:16px;}
.auth-field{margin-bottom:13px;}
.auth-field label{
  display:block;font-family:var(--mono);font-size:10px;letter-spacing:.16em;
  color:var(--ink-4);margin-bottom:6px;
}
.auth-field input{
  width:100%;font-family:var(--head);font-weight:300;font-size:15px;
  color:var(--capsule-ink);background:#fffdf7;
  border:1px solid var(--line);border-radius:2px;padding:10px 12px;min-height:42px;
}
.auth-actions{display:flex;align-items:center;flex-wrap:wrap;gap:10px 18px;margin-top:18px;}
.auth-submit{
  font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--ink-2);
  background:none;border:1px solid var(--line);border-radius:2px;
  padding:11px 22px;min-height:42px;cursor:pointer;transition:color .2s,border-color .2s;
}
.auth-submit:hover{color:var(--red-deep);border-color:var(--red-deep);}
.auth-swap{
  font-family:var(--sans);font-size:12px;color:var(--ink-3);
  background:none;border:0;border-bottom:1px solid transparent;padding:6px 0;cursor:pointer;
}
.auth-swap:hover{color:var(--red-deep);border-bottom-color:var(--red-deep);}
.auth-legal{
  margin-top:16px;padding-top:12px;border-top:1px solid var(--line);
  font-family:var(--mono);font-size:9.5px;letter-spacing:.08em;color:var(--ink-4);
}

/* ---------- responsive ---------- */
@media (max-width:900px){
  .feature,.home-grid,.series-card,.series-row,.series-hero,.chapter,.chapter:nth-child(even){grid-template-columns:1fr;}
  .chapter:nth-child(even) .art{order:0;justify-self:auto;}
  /* .chapter and .series-row are fixed-size, not text-driven (see their
     base rules) — that doesn't change here, but going single-column drops
     the outer-edge pinning (no row to be "outer" in any more), so they
     centre instead. .series-hero stays untouched: it's a one-per-page
     hero and keeps the cap-and-centre treatment at every width. */
  .chapter .art,.series-row .art{
    justify-self:auto;margin-inline:auto;
  }
  .series-hero .art{
    align-self:auto;justify-self:auto;
    height:auto;width:100%;max-height:none;min-height:0;
    max-width:24rem;margin-inline:auto;
  }
  .standalone-grid{grid-template-columns:1fr 1fr;}
}
@media (max-width:560px){
  .nav{gap:18px;}
  .two-up,.standalone-grid,.article-nav{grid-template-columns:1fr;}
  .article-nav a.next{text-align:inherit;}
  .margins .entry{grid-template-columns:1fr;gap:6px;}
  /* Reading on a phone: the clamp() floors already keep the type at a
     readable size, so the only thing worth protecting is the inner margin —
     the capsule must not squeeze the column against its own edge. Line
     height eases very slightly because the measure is narrower here. */
  .capsule{padding:clamp(28px,7vw,40px) clamp(20px,5.5vw,30px);}
  .prose{line-height:1.82;}
  /* justify without hyphenation reads as ragged gaps on a narrow Hebrew
     column - keep it desktop-only, fall back to normal start-alignment. */
  .prose p{text-align:start;}
  .about-head{flex-direction:column;align-items:flex-start;gap:16px;}
  .about-photo{width:96px;height:96px;}
  /* keep the drop cap from swallowing a short first line on a narrow column */
  .prose .lede::first-letter{font-size:2.35em;margin-inline-end:.1em;}
  .article-hero .num{margin:16px 0 14px;}
  .article-hero h1{margin-bottom:22px;}
  /* utilities stay the same size on a phone; only their hit area grows, to
     clear the 44px touch target without turning them into buttons */
  .art-utils{gap:0 22px;}
  .art-utils .util{min-height:44px;}
  /* the two continuation slots stack rather than squeeze */
  .article-nav .next{text-align:inherit;}
  /* Notes on a phone. Type size is left alone — the fix for a narrow column
     is a shallower indent and bigger hit areas, not smaller letters. The
     indent guide stays, so the thread is still readable as a thread. */
  .note-children{padding-inline-start:13px;}
  .note-reply,.reply-cancel{min-height:44px;}
  .notes-gate-btn,.composer-submit,.notes-demo-btn{min-height:44px;}
  .composer-actions{justify-content:flex-start;}
  .notes-demo-btn{margin-inline-start:0;}
  .mention-menu{max-width:calc(100vw - 2*var(--gutter) - 4px);}
  .auth-form{padding:20px 18px 18px;}
}
@media (prefers-reduced-motion:reduce){
  *{animation:none !important;transition:none !important;}
}

/* ---------- print: the article, and only the article ----------
   The whole point of the print button is reading OFF the screen, so the
   printed page keeps nothing of the screen world: no atmosphere, no nav,
   no capsule chrome — black serif text on plain paper, the title, the
   standfirst, and the byline. Pull quotes keep their rules (ink-cheap). */
@media print{
  /* everything that belongs to the screen: the Solaris scene and its moving
     objects, the site chrome, the series controls, the utilities, and the
     hero artwork. What survives is the title, the standfirst, the byline
     line, and the body with its pull quotes. */
  .atmos,.depth,.skip,.site-header,.newsletter-band,.site-footer,
  .article-nav,.art-utils,.series-dna,.notes,.auth-dialog,
  .article-hero .art,.article-hero .series-link{display:none !important;}
  body::after{display:none !important;}   /* the reading scrim */
  body{background:#fff;color:#000;font-weight:400;}
  .wrap{max-width:100%;padding:0;}
  main{padding:0;}
  .article-hero{margin-bottom:24pt;}
  .article-hero h1{color:#000;font-size:26pt;}
  .article-hero .deck{color:#222;font-size:14pt;max-width:none;}
  .article-hero .num,.article-hero .meta{color:#444;}
  .capsule{background:#fff;color:#000;border:none;box-shadow:none;max-width:100%;padding:0;}
  .capsule::before{display:none;}
  .prose{font-size:11.5pt;line-height:1.75;}
  .prose p{max-width:none;}
  .prose .lede::first-letter{color:#000;}
  .prose blockquote{border-color:#888;}
  .prose blockquote p{color:#333;}
  .content-image{max-width:100%;}
  a{text-decoration:none;color:inherit;}
  /* the preview flag stays: a printed copy of an unpublished piece should
     say so on the paper, not only on the screen it came from. */
  .preview-flag{color:#333;border-top-color:#000;}
  .preview-flag b{color:#000;}
}
