/* ══════════════════════════════════════════════════════════════════
   LAYMON GAMES — layout-fix.css

   Additive correction layer, loaded last. Everything in here fixes
   something that measures wrong today; nothing in here is a new idea.

   Each block names the measurement it corrects, taken at 1440×900 and
   360×780 before the change.
   ══════════════════════════════════════════════════════════════════ */

/* ──────────────── 1 · the About heading was invisible ────────────────
   motion.css clips every .shead__title to zero width and unclips it from
   `.shead.is-in`. The About heading is the only one that was not inside a
   .shead, so it never unclipped: clip-path stayed inset(0 100% 0 0) and
   `<h2 id="aboutTitle">` — the accessible name of the whole section — was
   painted at zero width in both languages and at every width. */
.about .shead__title,
.about .shead.is-in .shead__title { clip-path: none }

/* ──────────────── 2 · the About column had a 115px hole ────────────────
   The eyebrow sat at the top of a column whose tallest item was the
   portrait, and the lead paragraph was centred against it, so the heading
   was pushed ~100px below the eyebrow and read as unrelated to it. */
.about { align-items: start }
.about__prose { padding-block-start: clamp(0rem, 3vh, 2.4rem) }
.about .shead { margin-block-end: .9rem }

/* ──────────────── 3 · the terminal outgrew the card ────────────────
   Two measurements, one cause: a fixed 24em min-block-size on a 12.4px
   base. At ≥1081px the card's left column wants 339px and the block was
   331px, so the grid stretched it to ~450px and left a 300px void between
   the paragraph and the listing. Below that the base is still 12.4px
   against a 260px column, so the longest JS line ran 374px wide and the
   listing carried a horizontal scrollbar.

   The floor is kept where it is doing real work — a desktop card whose
   height should not jump while the listing types — and scaled to the
   column everywhere the column, not the content, is the constraint. */
.term__out { min-block-size: 22em }

@media (max-width: 1080px) {
	.skill--lead .term__out { min-block-size: 22em }
}
@media (max-width: 640px) {
	/* The widest line in the listing is 55 characters; JetBrains Mono advances
	   0.6em, so fitting a 281px column outright would need 8.5px — below
	   reading size. The listing therefore keeps the horizontal scroll it
	   always had, and only the block height comes down with the type. */
	.term__out { font-size: 11px; min-block-size: 18em }
}

/* the card's own empty band, independent of the terminal */
.skill--lead .skill__d { max-inline-size: 42ch }

/* the step number was set flush against the dot and clipped by the rail line,
   so "01" read as "0I". It now clears the dot and its label sits under it.

   The number is a marker that sits ON the rail, not beside it. The rail is a
   1px line at y = flow.top + 3, and the number's own box is 12.5px tall with its
   top at the same y — so the line ran through the vertical middle of the digits
   and struck them out: measured at 1440, line y = 347.6 inside a number box
   spanning 344.6–357.1. Giving the number a plate means the marker interrupts
   the rail the way a station interrupts a track, which is the reading that was
   intended, instead of the rail interrupting the number. */
.flow__num {
	display: inline-block;
	/* Clear of the dot but still overlapping the rail, so the rail runs up to
	   the digits and stops underneath them. The dot is 7px at x = 100–107; this
	   puts the glyphs at 133.6, so the dot's silhouette is never covered. */
	padding: .2em .58em .2em 1.55em;
	border-radius: 3px;
	background: var(--ink);
	letter-spacing: .16em;
	/* The plate would otherwise cover the 1px rail, and on a fresh reveal the
	   rail's leading end is the only thing joining the dot to the list. The mask
	   makes exactly the dot's own width (7px) transparent and everything after
	   it opaque, so the plate begins where the dot ends — dot, then number, with
	   no unlit gap between them. */
	-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 7px);
	mask-image: linear-gradient(90deg, transparent 0, #000 7px);
}
html[dir="rtl"] .flow__num {
	padding: .2em 1.55em .2em .58em;
	-webkit-mask-image: linear-gradient(270deg, transparent 0, #000 7px);
	mask-image: linear-gradient(270deg, transparent 0, #000 7px);
}

/* ──────────────── 4 · the process rail was geometrically wrong ────────────────
   styles.css sets the rail to `calc(--flow-col*3 + --flow-gap*3)` from the
   inline-start edge, which is 1001px of a 1240px grid: the first three dots
   sat on it and the fourth landed 66px past its end, outside the line it is
   supposed to terminate.

   The rail now spans from the first dot to the last. --flow-dot is the one
   number both the dots and the rail are placed with, so they cannot drift
   apart again if the padding is retuned. */
.flow {
	--flow-dot: 1.55rem;
	--flow-span: calc(var(--flow-col) * 3 + var(--flow-gap) * 3);
}
.flow::before {
	inset-inline-start: var(--flow-dot);
	inline-size: var(--flow-span);
}

/* .flow__step::after scales with --step-y, which no script ever wrote, so the
   narrow-screen spine was sitting at scaleY(0) — a vertical process list with
   no line connecting it, and no error anywhere to say why. */
@media (max-width: 900px) {
	/* styles.css takes the rail out with `content:none` on .flow::before.
	   That is a content-level reset which this file's later background and
	   transform declarations do not override, so it has to be repeated here:
	   without it a 900px-wide element draws across a single-column list and
	   reads as a stray horizontal gold bar. Same for the current that rides
	   the rail — there is no rail left to ride. */
	.flow::before,
	.flow::after { content: none }
	.js [data-reveal="flow"] .flow__step::after { transform: none }
	/* with the rail gone there is no line for the number to interrupt, so the
	   plate and its offset are dropped and the label sits plain beside the dot */
	.flow__num {
		margin-inline-start: 0;
		padding: 0;
		background: none;
		border-radius: 0;
		-webkit-mask-image: none;
		mask-image: none;
	}
	/* The spine sits in the flow's 1.9rem inline-start padding, and the dots
	   are centred on it rather than left-flush against it: styles.css put them
	   at -1.9rem (flush with the spine's start edge, but on the wrong side of
	   the step, so they read as belonging to the previous item) while the step
	   text sits a further 1.1rem in. Centring a 7px dot on a 1px line needs
	   half its own width back. */
	.flow__step::after { inset-inline-start: -1.9rem }
	.flow__dot { inset-inline-start: calc(-1.9rem + 3.5px) }
}

/* ──────────────── 5 · section rhythm was lopsided ────────────────
   --sec is a min/max clamp, so at 1440×900 every section took the 99px
   ceiling while the hero took 124/81. The first and last band on the page
   should be the two that breathe; the interior sections should not out-space
   the hero. Trimmed to 88px at the top end and given its own line on a
   phone, where 86px top and 86px bottom between every section added up to a
   page with more gap than content. */
.sec { padding-block: clamp(4rem, 9.5vh, 5.5rem) }
@media (max-width: 640px) {
	.sec { padding-block: clamp(3.4rem, 8vh, 4.6rem) }
}

/* ──────────────── 6 · the feature's right column floated ────────────────
   265px of copy against a 373px image left the project name and its spec
   floating in the middle of an empty column. It is centred against the art
   deliberately, but the extra space should be under it, not above it. */
@media (min-width: 901px) {
	.feature__body { align-self: center; padding-block: .5rem }
}

/* ──────────────── 7 · the archive rows had a two-column gap ────────────────
   Below 640px the grid drops to two columns and the arrow was hidden, so the
   row's destination had nowhere to live. It is shown again — it is the only
   "where does this go" cue on a phone — and the thumbnail gives back the
   space. */
@media (max-width: 640px) {
	.row { grid-template-columns: 88px minmax(0, 1fr) 16px; gap: .75rem }
	.row__go { display: inline-flex; inline-size: 16px }
	.row:hover .row__go::before,
	.row:focus-visible .row__go::before { max-inline-size: 0; opacity: 0 }
	.row__go { color: var(--gold) }
}

/* ──────────────── 8 · the hero's field stopped above the wordmark ────────────────
   hero__field is masked out by 42% and hero__halo sits behind the mascot, so
   the lower two-thirds of a tall viewport was a flat black rectangle with a
   canvas that had already faded out. The mask now reaches further down so the
   texture carries under the kicker; the opacity stays where it was, because
   the hero must keep exactly one accent. */
.hero__field {
	inset: 0 0 26% 0;
	block-size: 74%;
	mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .5) 58%, transparent 100%);
}

/* ──────────────── 9 · the burger icon sat 11.7px above its own button ────────────────
   `.burger` is a column flex box with `place-items: center`. In a column flex
   container, `align-items` is the CROSS axis (horizontal) and `justify-content`
   is the MAIN axis (vertical) — `place-items` only sets align-items, so
   justify-content stayed at its initial `normal`, i.e. flex-start. The icon was
   pinned to the top edge of the 38px circle:

     button centre y = 31.0   bars centre y = 19.25   offset = -11.7px

   Symmetric on small screens, but 31% of the button's height off centre, at
   every breakpoint below 900px.

   The icon itself is now two vector states instead of three rotated 1.5px divs.
   At 15x1.5px a 45° rotation produces ~2px diagonals that anti-alias into a
   blot rather than a cross, and no amount of sub-pixel nudging fixes a shape
   whose stroke width changes when it rotates.

   `display: grid` is wrapped in the same breakpoint as `styles.css` uses to
   reveal the button. Declaring it unconditionally overrode
   `@media (max-width:900px){ .burger{ display:flex } }` — which is a *reveal*,
   not a layout tweak — so the burger became visible on desktop, where there is
   no drawer to open and the nav already carries every link. */
@media (max-width: 900px) {
	.burger { display: grid; grid-template-areas: 'icon'; justify-content: center; place-items: center; position: relative }
}
.burger__menu,
.burger__close {
	grid-area: icon;
	inline-size: 18px;
	block-size: 14px;
	color: var(--cream);
	transition: opacity .22s ease, scale .28s cubic-bezier(.16, 1, .3, 1);
}
/* both states occupy the same grid cell, so the button's box never depends on
   which icon is showing */
.burger__close { opacity: 0; scale: .82 }
.burger[aria-expanded="true"] .burger__menu { opacity: 0; scale: .82 }
.burger[aria-expanded="true"] .burger__close { opacity: 1; scale: 1 }
.burger:hover .burger__menu,
.burger:hover .burger__close { color: var(--gold-hi) }
/* the three <i> bars are gone from the markup; this retires the rules that
   styled them in styles.css so nothing is left half-matching */
.burger i { display: none }

/* ──────────────── 10 · a phone's first screen was 226px of empty black ────────────────
   The hero is `min-block-size: 100svh` and a grid with `place-items: center`,
   and the sticky nav already occupies the top 63px. So on top of that the hero
   held a `calc(nav + clamp(1.8rem, 6vh, 4.4rem))` top pad AND centred its
   content in what was left over:

     360x780   nav bottom 63   mascot top 289   ->  226px of nothing
     320x700                      239            ->  176px
     390x844                      335            ->  272px  (worse, taller phone)
     768x1024                     391            ->  328px

   Making the hero exactly the viewport MINUS the nav means the pads now do the
   spacing instead of sharing it with a second layer of auto margins, and the
   mask-image on the field fades the grid out well before the wordmark, so the
   band never reads as an unpainted rectangle. */
.hero { min-block-size: calc(var(--vh) - var(--nav-h)) }

@media (max-width: 900px) {
	/* the vh term stops winning above ~800px tall, so the pad stops
	   over-running on exactly the phones that had the most slack */
	.hero {
		padding-block: calc(var(--nav-h) + clamp(1.1rem, 3.4vh, 2.4rem))
		                clamp(2.6rem, 6vh, 4rem);
	}
}

/* ──────────────── 11 · section rhythm on a phone ────────────────
   Sections are separated by rhythm rather than by boxes, and at 360px every
   one of them opened with a hairline-thin eyebrow floating at the top of a
   ~70px empty band, which reads as a hole rather than as space. The band is
   tightened and the sections are separated by a hairline instead, so the
   rhythm is carried by a mark rather than by absence. On a pointer nothing
   changes: the hairlines are only worth having where the space is scarce. */
@media (max-width: 640px) {
	.sec { padding-block: clamp(2.9rem, 7vh, 3.9rem) }
	main > .sec + .sec { border-block-start: 1px solid var(--line-2) }
	/* and the anchor target clears the sticky bar instead of tucking under it */
	main > .sec { scroll-margin-block-start: var(--nav-h) }
}

/* ──────────────── 12 · About led with the photo and buried its own text ────────────────
   On narrow screens the portrait is ordered first, so a 4/5 image in a ~340px
   column measures 455px tall. Measured on a 360x780 phone: the figure occupied
   y 82–538, the heading began at 623, and the two bio paragraphs and the
   signature ran from 678 to 784. Every word of the section's content was below
   the fold, and the *name* of the section — `<h2 id="aboutTitle">` — sat 480px
   down a screen whose first 538px were one photograph.

   `styles.css` sets order:-1 on the figure below 900px, which is the right call
   for a portrait-led teaser and the wrong one for a section whose job is to say
   who the studio is. The markup already has the prose first and the portrait
   second, so the narrow-screen override simply stops fighting it: text, then
   the face. Nothing is cropped, nothing is moved in the DOM, and the desktop
   two-column layout beside the portrait is untouched.

   The image still gets a height budget rather than being as tall as its column,
   so on a short phone it cannot swallow the screen on its own. */
@media (max-width: 900px) {
	/* `styles.css` also carries an explicit `html[dir="rtl"] .about__figure
	   { order: -1 }`. A single-class override loses to that on specificity, and
	   the symptom was Arabic still leading with the photograph while English had
	   already switched — so both selectors are named here rather than relying on
	   source order. */
	html[dir="rtl"] .about__figure { order: 0 }
	.about__figure {
		order: 0;
		max-inline-size: 26rem;
	}
	/* a real gap between the picture and its own caption — the image used to be
	   the element that grew on hover, so the words sat right under it */
	.about__figure figcaption { margin-block-start: 1.1rem }
	.about__figure img {
		block-size: min(44svh, 26rem);
		aspect-ratio: auto;
	}
}

