/* site/src/assets/css/page-work.css
 * The portfolio page only. Order: intro, the proving ground shell, the
 * control deck, a case study, the drawn screens, the four conditions, the
 * honest note, the next step.
 *
 * The one idea here is that the page can be broken on purpose. A condition
 * chosen in the deck sets data-hazard on .rig, and every state below hangs
 * off that one attribute — so the three projects all react at the same
 * instant and visibly disagree about how well they cope. Nothing is hidden
 * when a condition is on: the written answers stay on the page and the live
 * one is only highlighted, so a screen reader loses nothing.
 */

/* ── intro ───────────────────────────────────────────────────────────── */
.w-intro {
	background: var(--paper);
	padding: clamp(110px, 16vh, 190px) var(--gutter) clamp(56px, 9vh, 96px);
	/* Holds every child to the same --wide column the rig and the cases use,
	   so on a big screen the intro does not hug the left edge alone. */
	padding-inline: max(var(--gutter), (100% - var(--wide)) / 2);
}

.w-intro__kicker { color: #9a6a12; }

.w-intro__h {
	max-width: var(--wide);
	margin: 14px 0 0;
	font: 800 clamp(40px, 8.4vw, 132px)/.9 var(--display);
	letter-spacing: -.045em;
}
.w-intro__h em {
	font-style: normal;
	/* A highlighter rather than coloured text: the loud version still holds
	   full contrast against the paper. */
	background: linear-gradient(var(--yellow), var(--yellow)) 0 88% / 100% .34em no-repeat;
	padding: 0 .06em;
}

.w-intro__lead {
	max-width: 54ch;
	margin-top: clamp(22px, 3.4vh, 34px);
	font-size: clamp(17px, 1.35vw, 21px);
}
.w-intro__lead--soft { color: var(--ink-soft); }

.w-intro__jump {
	list-style: none;
	margin-top: clamp(28px, 4vh, 44px);
	display: flex; flex-wrap: wrap; gap: 10px;
}
.w-intro__jump a {
	display: inline-flex; align-items: center; gap: 10px;
	min-height: 44px; padding: 0 18px;
	border: 1.5px solid var(--line); border-radius: 999px;
	font: 500 13px/1 var(--mono); letter-spacing: .06em;
	text-decoration: none;
	transition: background .2s, color .2s, border-color .2s;
}
.w-intro__jump a b { font: 700 13px/1 var(--mono); color: #9a6a12; }
.w-intro__jump a:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.w-intro__jump a:hover b { color: var(--yellow); }

/* ── the proving ground ──────────────────────────────────────────────── */
/* No overflow rule here on purpose: the deck inside is position: sticky and
   any clipping ancestor would kill it. */
.rig {
	background: var(--ink);
	color: var(--paper);
	padding: clamp(64px, 10vh, 120px) var(--gutter) clamp(40px, 6vh, 80px);
	transition: background .5s;
}
.rig[data-hazard="power"] { background: #04040a; }

.rig__head { max-width: var(--wide); margin: 0 auto; display: grid; gap: 12px; }
.rig__kicker { color: var(--amber); }
.rig__title {
	font: 800 clamp(34px, 5.6vw, 88px)/.94 var(--display);
	letter-spacing: -.04em;
}
.rig__sub { color: rgba(251, 249, 244, .68); max-width: 52ch; }

/* ── the control deck ────────────────────────────────────────────────── */
/* Sticky to the bottom of the viewport, not the top: the fixed nav already
   owns the top edge, and on a phone the thumb lives down here anyway. It is
   early in the DOM so keyboard users reach the controls before the three
   case studies they operate on. */
.deck {
	position: sticky;
	bottom: 0;
	z-index: 20;
	max-width: var(--wide);
	margin: clamp(28px, 4vh, 48px) auto 0;
	padding: 14px 16px 16px;
	border: 1px solid rgba(251, 249, 244, .16);
	border-radius: 18px;
	background: rgba(10, 10, 15, .92);
	backdrop-filter: blur(10px);
	box-shadow: 0 -18px 40px rgba(0, 0, 0, .55);
	display: grid; gap: 10px;
}

.deck__title { color: var(--amber); }

.deck__row { display: flex; flex-wrap: wrap; gap: 8px; }

.hz {
	display: inline-flex; align-items: center; gap: 8px;
	min-height: 44px; padding: 0 16px;
	border: 1.5px solid rgba(251, 249, 244, .28);
	border-radius: 999px;
	background: transparent;
	color: var(--paper);
	font: 500 13px/1 var(--mono); letter-spacing: .05em;
	cursor: pointer;
	transition: background .18s, color .18s, border-color .18s, transform .18s;
}
.hz:hover { border-color: var(--paper); transform: translateY(-1px); }
.hz__sign { font-size: 14px; opacity: .8; }
.hz[aria-pressed="true"] {
	background: var(--yellow);
	border-color: var(--yellow);
	color: var(--ink);
}
.hz[aria-pressed="true"] .hz__sign { opacity: 1; }
.hz--clear[aria-pressed="true"] { background: var(--teal); border-color: var(--teal); }

.deck__readout {
	font: 400 13px/1.4 var(--mono);
	color: rgba(251, 249, 244, .62);
}

/* ── a case study ────────────────────────────────────────────────────── */
.cases {
	max-width: var(--wide);
	margin: 0 auto;
	display: grid;
	gap: clamp(28px, 5vh, 56px);
	/* Room for the pinned deck so the last paragraph is never sitting under
	   it. */
	padding-block: clamp(32px, 5vh, 56px) clamp(120px, 18vh, 180px);
}

.case {
	--case: var(--teal);
	position: relative;
	padding: clamp(24px, 3.6vw, 48px);
	border: 1px solid rgba(251, 249, 244, .14);
	border-radius: 22px;
	background: #101018;
	scroll-margin-top: 92px;
}
.case--nox { --case: var(--teal); }
.case--saf { --case: var(--amber); }
.case--ops { --case: #6f96ff; }

/* A coloured spine so the three read as three, even at a glance. */
.case::before {
	content: '';
	position: absolute; left: 0; top: clamp(24px, 3.6vw, 48px); bottom: clamp(24px, 3.6vw, 48px);
	width: 4px; border-radius: 0 4px 4px 0;
	background: var(--case);
}

.case__head { display: grid; gap: 8px; }
.case__num {
	font: 800 clamp(40px, 6vw, 82px)/.8 var(--display);
	letter-spacing: -.05em;
	color: transparent;
	-webkit-text-stroke: 1.5px var(--case);
}
.case__tag { color: var(--case); }
.case__title {
	font: 700 clamp(25px, 3.2vw, 46px)/1.02 var(--display);
	letter-spacing: -.035em;
	max-width: 22ch;
}

.case__grid {
	margin-top: clamp(22px, 3vh, 36px);
	display: grid;
	gap: clamp(24px, 3vw, 48px);
	grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
	align-items: start;
}

.case__sub {
	font: 500 12px/1 var(--mono);
	letter-spacing: .16em; text-transform: uppercase;
	color: var(--case);
	margin: clamp(20px, 2.6vh, 28px) 0 10px;
}
.case__text > .case__sub:first-child { margin-top: 0; }
.case__sub--wide { margin-top: clamp(26px, 3.4vh, 40px); }

.case__text p { color: rgba(251, 249, 244, .78); max-width: 62ch; }

.case__list { list-style: none; display: grid; gap: 9px; max-width: 62ch; }
.case__list li {
	position: relative;
	padding-left: 22px;
	color: rgba(251, 249, 244, .78);
}
.case__list li::before {
	content: '';
	position: absolute; left: 0; top: .62em;
	width: 9px; height: 9px; border-radius: 2px;
	background: var(--case);
}

.case__note {
	margin-top: 14px;
	font: 400 13px/1.5 var(--mono);
	color: rgba(251, 249, 244, .5) !important;
	border-left: 2px solid rgba(251, 249, 244, .22);
	padding-left: 12px;
}

.case__domain { font-family: var(--mono); font-size: .92em; color: var(--case); }

.case__keep {
	margin-top: clamp(22px, 3vh, 32px);
	padding: 18px 20px;
	border-radius: 14px;
	background: rgba(251, 249, 244, .06);
	color: rgba(251, 249, 244, .82);
	max-width: 70ch;
}
.case__keep b { color: var(--paper); }

.case__warn {
	margin-top: 14px;
	padding: 18px 20px;
	border-radius: 14px;
	border: 1px dashed rgba(255, 176, 32, .5);
	color: rgba(251, 249, 244, .74);
	font-size: .94em;
	max-width: 70ch;
}
.case__warn b { color: var(--amber); }

/* ── the four conditions, written out ────────────────────────────────── */
.survives { display: grid; gap: 10px; }

.survive {
	display: grid;
	gap: 4px;
	padding: 14px 16px;
	border-radius: 12px;
	border: 1px solid rgba(251, 249, 244, .12);
	background: rgba(251, 249, 244, .03);
	transition: background .3s, border-color .3s, transform .3s;
}
.survive dt {
	display: flex; align-items: center; gap: 10px;
	font: 500 12px/1 var(--mono);
	letter-spacing: .14em; text-transform: uppercase;
	color: rgba(251, 249, 244, .6);
}
.survive dd { color: rgba(251, 249, 244, .8); max-width: 70ch; }
.survive__sign { font-size: 14px; }

/* The live condition is lit rather than isolated — the other three stay
   readable, which is the whole reason nothing is hidden. */
.rig[data-hazard="power"] .survive[data-when="power"],
.rig[data-hazard="slow"] .survive[data-when="slow"],
.rig[data-hazard="small"] .survive[data-when="small"],
.rig[data-hazard="offline"] .survive[data-when="offline"] {
	background: rgba(251, 249, 244, .1);
	border-color: var(--case);
	transform: translateX(4px);
}
.rig[data-hazard="power"] .survive[data-when="power"] dt,
.rig[data-hazard="slow"] .survive[data-when="slow"] dt,
.rig[data-hazard="small"] .survive[data-when="small"] dt,
.rig[data-hazard="offline"] .survive[data-when="offline"] dt { color: var(--case); }

/* The one that openly fails is marked in warning colour, not in the case
   colour: a failure should not look like a feature. */
.rig[data-hazard="offline"] .survive--fails { border-color: var(--pink); }
.rig[data-hazard="offline"] .survive--fails dt { color: var(--pink); }
.survive--fails dd b { color: var(--pink); }

/* ── the drawn screens ───────────────────────────────────────────────── */
.case__stage { display: grid; gap: 10px; justify-items: center; }

.case__ruler {
	font: 400 11px/1.4 var(--mono);
	letter-spacing: .06em;
	color: rgba(251, 249, 244, .42);
	text-align: center;
}

.screen {
	position: relative;
	width: clamp(178px, 19vw, 232px);
	border-radius: 20px;
	padding: 8px;
	background: #1a1a24;
	border: 1px solid rgba(251, 249, 244, .16);
	box-shadow: 0 24px 50px rgba(0, 0, 0, .5);
	transition: width .45s, filter .35s;
}
.screen--browser { width: clamp(200px, 24vw, 300px); border-radius: 12px; }
.screen--tablet { width: clamp(190px, 22vw, 268px); border-radius: 14px; }

.screen__glass {
	position: relative;
	display: grid; gap: 8px;
	padding: 12px;
	border-radius: 13px;
	background: radial-gradient(120% 80% at 50% 0%, rgba(255, 255, 255, .07), #07070c 70%);
	min-height: 190px;
	align-content: start;
	overflow: hidden;
	transition: filter .35s;
}
.screen--browser .screen__glass { border-radius: 0 0 8px 8px; }

.screen__chrome {
	display: flex; align-items: center; gap: 5px;
	padding: 7px 9px;
	border-radius: 8px 8px 0 0;
	background: #23232e;
}
.screen__chrome .dot { width: 7px; height: 7px; border-radius: 50%; background: rgba(251, 249, 244, .3); }
.screen__bar { flex: 1; height: 8px; margin-left: 6px; border-radius: 99px; background: rgba(251, 249, 244, .14); }

.screen__media { position: relative; border-radius: 8px; overflow: hidden; }

/* NOXERA: a voice meter. It is the listening that is worth drawing. */
.screen__media--voice {
	display: flex; align-items: flex-end; justify-content: center; gap: 5px;
	height: 92px; padding: 10px;
	background: radial-gradient(60% 70% at 50% 100%, rgba(0, 217, 184, .22), transparent 70%);
}
.screen__media--voice .bar {
	width: 7px; height: 16px; border-radius: 99px;
	background: linear-gradient(var(--teal), #0b7f6d);
	transform-origin: bottom;
	animation: wk-bar 1.15s ease-in-out infinite alternate;
	animation-delay: calc(var(--i) * .085s);
}
/* Ends on the resting height, so a reduced-motion browser that collapses the
   animation still shows a sensible meter. */
@keyframes wk-bar {
	0% { transform: scaleY(1); }
	50% { transform: scaleY(3.4); }
	100% { transform: scaleY(1); }
}

/* Almado: the photograph, because the photograph is the product. */
.screen__media--photo { height: 104px; }
.screen__scene { display: block; width: 100%; height: 100%; }

/* Conference Ops: the register, with invented rows. */
.screen__media--rows { display: grid; gap: 6px; }
.screen__media--rows .row {
	display: flex; align-items: center; justify-content: space-between; gap: 8px;
	padding: 7px 9px;
	border-radius: 7px;
	background: rgba(251, 249, 244, .07);
	font: 400 10px/1 var(--mono);
	color: rgba(251, 249, 244, .7);
}
.screen__media--rows .row i { font-style: normal; letter-spacing: .05em; }
.screen__media--rows .row b {
	width: 18px; height: 18px; border-radius: 5px;
	border: 1.5px solid rgba(251, 249, 244, .35);
	background: transparent;
	animation: wk-tick 5s ease-out infinite;
	animation-delay: calc(var(--i) * .45s);
}
@keyframes wk-tick {
	0%, 6% { background: transparent; border-color: rgba(251, 249, 244, .35); }
	14%, 100% { background: var(--teal); border-color: var(--teal); }
}

.screen__stamp {
	justify-self: start;
	font: 500 9px/1 var(--mono);
	letter-spacing: .2em; text-transform: uppercase;
	color: rgba(255, 176, 32, .85);
	border: 1px solid rgba(255, 176, 32, .5);
	border-radius: 4px;
	padding: 4px 6px;
}

.screen__line {
	font: 400 11px/1.3 var(--mono);
	color: rgba(251, 249, 244, .72);
	transition: color .3s, background .3s;
}
.screen__line--dim { color: rgba(251, 249, 244, .38); }

/* Only the badge for the live condition shows. The screens are aria-hidden
   decoration, so nothing is lost by swapping them. */
.screen__badge {
	display: none;
	position: absolute; right: -8px; bottom: 14px;
	padding: 6px 10px;
	border-radius: 999px;
	background: var(--paper);
	color: var(--ink);
	font: 500 10px/1 var(--mono);
	letter-spacing: .08em;
	box-shadow: 0 8px 18px rgba(0, 0, 0, .45);
	transform: rotate(-3deg);
}
.screen__badge--good { background: var(--teal); }
.screen__badge--bad { background: var(--pink); color: #2a0010; }
.rig[data-hazard="none"] .screen__badge[data-when="none"],
.rig[data-hazard="power"] .screen__badge[data-when="power"],
.rig[data-hazard="slow"] .screen__badge[data-when="slow"],
.rig[data-hazard="small"] .screen__badge[data-when="small"],
.rig[data-hazard="offline"] .screen__badge[data-when="offline"] { display: block; }

/* ── what each condition does to a screen ────────────────────────────── */

/* Power: the flicker, the dark, and the coming back. It loops, because the
   point is that the screens on either side come back differently. */
.rig[data-hazard="power"] .screen__glass { animation: wk-blackout 5.5s ease-in-out infinite; }
@keyframes wk-blackout {
	0% { filter: none; }
	6% { filter: brightness(2.2) contrast(1.3); }
	10% { filter: brightness(.04); }
	58% { filter: brightness(.04); }
	66% { filter: brightness(.35) saturate(.6); }
	74%, 100% { filter: none; }
}

/* 2G: the pictures become skeletons and the words become grey bars, which is
   what a thin line actually looks like before anything arrives. */
.rig[data-hazard="slow"] .screen__media > * { opacity: .1; }
.rig[data-hazard="slow"] .screen__media::after {
	content: '';
	position: absolute; inset: 0;
	background: linear-gradient(100deg, #191922 34%, #2f2f3d 50%, #191922 66%);
	background-size: 320% 100%;
	animation: wk-wipe 1.9s linear infinite;
}
@keyframes wk-wipe {
	0% { background-position: 130% 0; }
	100% { background-position: -130% 0; }
}
.rig[data-hazard="slow"] .screen__line {
	color: transparent;
	background: rgba(251, 249, 244, .12);
	border-radius: 4px;
	width: 70%;
}
.rig[data-hazard="slow"] .screen__line--dim { width: 45%; }

/* 360px: everything squeezes to the width most of Kenya browses on. */
.rig[data-hazard="small"] .screen,
.rig[data-hazard="small"] .screen--browser,
.rig[data-hazard="small"] .screen--tablet { width: 152px; }
.rig[data-hazard="small"] .case__grid { grid-template-columns: minmax(0, 1fr); }

/* No line: the colour drains and a hatch goes over the glass. The badges are
   what separate the three — one keeps working, one keeps its page, one
   plainly cannot save. */
.rig[data-hazard="offline"] .screen__glass { filter: grayscale(.92) brightness(.75); }
.rig[data-hazard="offline"] .screen__glass::after {
	content: '';
	position: absolute; inset: 0;
	background: repeating-linear-gradient(46deg, rgba(251, 249, 244, .07) 0 7px, transparent 7px 16px);
	pointer-events: none;
}
/* The one that still answers keeps its colour and its meter. */
.rig[data-hazard="offline"] .case--nox .screen__glass { filter: none; }

/* Animation only runs while the rig is on screen and the tab is in front;
   work.js sets data-live. With no JS at all nothing animates, which is the
   right resting state for a static page. */
.rig:not([data-live="on"]) .screen,
.rig:not([data-live="on"]) .screen *,
.rig:not([data-live="on"]) .screen *::after { animation-play-state: paused; }

/* ── what is not on this page ────────────────────────────────────────── */
.w-honest {
	background: var(--paper);
	color: var(--ink);
	padding: clamp(60px, 9vh, 110px) var(--gutter);
	border-bottom: 1px solid var(--line);
}
.w-honest__title {
	max-width: var(--wide); margin: 0 auto;
	font: 800 clamp(28px, 4vw, 58px)/1 var(--display);
	letter-spacing: -.04em;
}
.w-honest__grid {
	max-width: var(--wide);
	margin: clamp(26px, 4vh, 44px) auto 0;
	display: grid; gap: clamp(24px, 3vw, 48px);
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.w-honest__grid h3 {
	font: 700 clamp(18px, 1.8vw, 24px)/1.1 var(--display);
	letter-spacing: -.02em;
	margin-bottom: 8px;
}
.w-honest__grid p { color: var(--ink-soft); max-width: 40ch; }

/* ── next step ───────────────────────────────────────────────────────── */
.w-next {
	background: var(--yellow);
	color: var(--ink);
	padding: clamp(60px, 10vh, 120px) var(--gutter);
	padding-inline: max(var(--gutter), (100% - var(--wide)) / 2);
}
.w-next__kicker { color: #7a5200; }
.w-next__title {
	margin: 12px 0 0;
	font: 800 clamp(34px, 6vw, 96px)/.94 var(--display);
	letter-spacing: -.045em;
}
.w-next__lead { max-width: 50ch; margin-top: 18px; font-size: clamp(16px, 1.2vw, 19px); }

.w-next__row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(26px, 4vh, 40px); }
.w-btn {
	display: inline-flex; align-items: center;
	min-height: 48px; padding: 0 22px;
	border: 2px solid var(--ink); border-radius: 999px;
	font: 500 14px/1 var(--mono); letter-spacing: .06em;
	text-decoration: none;
	transition: transform .2s, background .2s, color .2s;
}
.w-btn:hover { transform: translateY(-2px); }
.w-btn--go { background: var(--ink); color: var(--paper); }
.w-btn--go:hover { background: #22222c; }

.w-next__mail { margin-top: clamp(24px, 3.4vh, 36px); max-width: 52ch; }
.w-next__mail a { font-family: var(--mono); font-size: .94em; }

/* ── narrow screens ──────────────────────────────────────────────────── */
@media (max-width: 900px) {
	.case__grid { grid-template-columns: minmax(0, 1fr); }
	.case__stage { justify-items: start; }
}

@media (max-width: 560px) {
	.case { padding: 20px 16px; border-radius: 16px; }
	.case::before { top: 20px; bottom: 20px; }
	.deck { border-radius: 16px 16px 0 0; margin-left: calc(var(--gutter) * -1); margin-right: calc(var(--gutter) * -1); }
	.hz { padding: 0 13px; font-size: 12px; }
	.screen, .screen--browser, .screen--tablet { width: min(100%, 190px); }
	.survive { padding: 12px 13px; }
	.w-intro__jump a { width: 100%; }
}

/* ── motion ──────────────────────────────────────────────────────────── */
/* site.css already collapses animation for everyone who asks for less
   motion. The conditions still have to read as conditions, so each one gets
   a still version of itself here. */
@media (prefers-reduced-motion: reduce) {
	.screen, .survive, .rig { transition: none; }
	.rig[data-hazard="power"] .screen__glass { filter: brightness(.18); }
	.rig[data-hazard="slow"] .screen__media::after { background: #24242f; }
}
