/* ============================================================
   ADKline.Design — demo-web-tech.css
   Page-specific styles for /en/demo-web-tech.php

   Deliberately unminified. Each demo section is labelled.
   Read it alongside js/demos/demo-web-tech.js.
   ============================================================ */


/* ------------------------------------------------------------
   0. Registered custom properties (Demo 3 relies on --demo-hue
      being typed: the browser can then animate and clamp it)
   ------------------------------------------------------------ */
@property --demo-hue {
	syntax: "<number>";
	initial-value: 195;
	inherits: true;
}


/* ------------------------------------------------------------
   1. Self-hosted variable font (Demo 4)
      One file carries the whole design space:
      wght 100-900, opsz 9-144, SOFT 0-100, WONK 0-1
   ------------------------------------------------------------ */
@font-face {
	font-family: "Roboto Flex";
	src: url("../../fonts/roboto-flex/roboto-flex.woff2") format("woff2-variations");
	font-weight: 100 1000;
	font-display: swap;
}


/* ------------------------------------------------------------
   2. Shared demo chrome: stage + read-only code window
   ------------------------------------------------------------ */

/* Deep links from the intro chips land clear of the fixed navbar */
#demo-web-tech section[id] {
	scroll-margin-top: 5.5rem;
}


/* ------------------------------------------------------------
   2a. Hero background shader
       A transparent WebGL2 canvas behind the intro. It draws
       only soft low-alpha blobs, so the page background shows
       through and both themes work; the JS re-tints the field
       when data-bs-theme changes. Edges fade out via a mask so
       the canvas has no visible boundary.
   ------------------------------------------------------------ */
#intro {
	position: relative;
}

#hero-canvas {
	position: absolute;
	inset: 0;
	z-index: -1;
	width: 100%;
	height: 100%;
	pointer-events: none;
	-webkit-mask-image: radial-gradient(ellipse 75% 70% at 50% 45%, #000 45%, transparent 100%);
	mask-image: radial-gradient(ellipse 75% 70% at 50% 45%, #000 45%, transparent 100%);
}


/* ------------------------------------------------------------
   2b. Dark-mode contrast fixes
       main.min.css only defines badge-teal for the light theme
       (#285862 on #eef2f4), and Bootstrap's range track uses
       --bs-secondary-bg, which in dark mode almost matches the
       demo-stage background. Both get page-scoped overrides.
   ------------------------------------------------------------ */
#demo-web-tech .badge-teal {
	font-size: 0.95rem;
	padding: 0.55rem 0.95rem;
}

/* Back-pill to the demos listing: the arrow nudges left on hover */
.demo-back .bi-arrow-left {
	display: inline-block;
	transition: translate 0.2s ease;
}

.demo-back:hover .bi-arrow-left {
	translate: -3px 0;
}

[data-bs-theme="dark"] #demo-web-tech .badge-teal {
	color: #6fd6d0;
	background-color: rgba(111, 214, 208, 0.14);
}

/* -webkit- and -moz- track selectors must stay in separate rules:
   a browser drops the whole rule when it can't parse a selector */
[data-bs-theme="dark"] #demo-web-tech .form-range::-webkit-slider-runnable-track {
	background-color: rgba(255, 255, 255, 0.22);
}

[data-bs-theme="dark"] #demo-web-tech .form-range::-moz-range-track {
	background-color: rgba(255, 255, 255, 0.22);
}
.demo-stage {
	position: relative;
	border: 1px solid var(--bs-border-color);
	border-radius: 0.75rem;
	background-color: var(--bs-light-bg-subtle);
	padding: 1.25rem;
	min-height: 200px;
}

/* Small uppercase hint pinned to the stage corner */
.demo-hint {
	position: absolute;
	top: 0.6rem;
	right: 0.9rem;
	z-index: 3;
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: 0.62rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
	pointer-events: none;
}

/* The code window is always dark, in both site themes,
   the way an editor would be */
.demo-code {
	display: flex;
	flex-direction: column;
	height: 100%;
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: 0.75rem;
	overflow: hidden;
	background-color: #1c2128;
	font-size: 0.78rem;
}

.demo-code-header {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	padding: 0.55rem 1rem;
	background-color: #14181d;
	border-bottom: 1px solid rgba(255, 255, 255, 0.07);
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: 0.68rem;
	letter-spacing: 0.06em;
	color: #8b949e;
}

/* Faux window buttons */
.demo-code-dots {
	display: inline-flex;
	gap: 0.35rem;
}

.demo-code-dots i {
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background-color: #444c56;
}

.demo-code-dots i:nth-child(1) { background-color: #e5534b; }
.demo-code-dots i:nth-child(2) { background-color: #d4a72c; }
.demo-code-dots i:nth-child(3) { background-color: #57ab5a; }

.demo-code pre {
	flex: 1;
	margin: 0;
	padding: 1rem 1.1rem;
	overflow: auto;
	max-height: 380px;
	color: #adbac7;
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: inherit;
	line-height: 1.65;
	tab-size: 4;
}

.demo-code pre code {
	color: inherit;
	font-family: inherit;
	white-space: pre;
}

/* Minimal hand-rolled token colours (GitHub-dark-ish) */
.demo-code .tok-c { color: #768390; font-style: italic; }  /* comment  */
.demo-code .tok-p { color: #6cb6ff; }                      /* property */
.demo-code .tok-k { color: #f47067; }                      /* keyword  */
.demo-code .tok-s { color: #96d0ff; }                      /* string   */
.demo-code .tok-f { color: #dcbdfb; }                      /* function */

/* Values the JS rewrites while you interact */
.demo-code .live {
	color: #6fd6d0;
	font-weight: 700;
	border-radius: 0.25em;
}

.demo-code .live.flash {
	animation: demo-live-flash 0.7s ease-out;
}

@keyframes demo-live-flash {
	from { background-color: rgba(111, 214, 208, 0.35); }
	to   { background-color: transparent; }
}

/* Rule highlighting for demos 6 and 7: the block that currently
   matches is full strength, the others recede */
.demo-code .rule { transition: opacity 0.25s ease; }
.demo-code .rule.off { opacity: 0.4; }

/* Inline "not supported" notice used by several demos */
.demo-unsupported {
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: 0.72rem;
}


/* ------------------------------------------------------------
   3. Demo 1 — pointer-driven metaball shader (WebGL2)
   ------------------------------------------------------------ */
.shader-stage {
	position: relative;
	border-radius: 0.75rem;
	border: 1px solid var(--bs-border-color);
	overflow: hidden;
	aspect-ratio: 16 / 9;
	background-color: #0b0e14;   /* stays dark in both themes */
	cursor: crosshair;
}

#shader-canvas {
	display: block;
	width: 100%;
	height: 100%;
	touch-action: none;
}

.shader-hud {
	position: absolute;
	left: 0.8rem;
	bottom: 0.8rem;
	display: flex;
	gap: 1.1rem;
	padding: 0.4rem 0.7rem;
	border-radius: 0.5rem;
	border: 1px solid rgba(255, 255, 255, 0.12);
	background-color: rgba(11, 14, 20, 0.6);
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: 0.62rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: #9aa4b2;
	pointer-events: none;
}

.shader-hud b {
	color: #6fd6d0;
	font-weight: 600;
}


/* ------------------------------------------------------------
   4. Demo 2 — scroll-driven animations
      The scroller below is its own scroll container with a
      named scroll timeline. No JS drives the bar or the
      reveals in supporting browsers.
   ------------------------------------------------------------ */
.sda-scroller {
	position: relative;
	height: 300px;
	overflow-y: auto;
	border: 1px solid var(--bs-border-color);
	border-radius: 0.6rem;
	background-color: var(--bs-body-bg);
	scroll-timeline: --demo-scroll y;
}

/* Reading-progress bar, pinned inside the scroller */
.sda-progress {
	position: sticky;
	top: 0;
	z-index: 2;
	height: 6px;
	background-color: var(--bs-border-color);
}

.sda-progress i {
	display: block;
	height: 100%;
	background: linear-gradient(90deg, #2A5F62, #6fd6d0);
	transform-origin: left;
	scale: 0 1;
	animation: sda-fill linear both;
	animation-timeline: --demo-scroll;
}

@keyframes sda-fill {
	to { scale: 1 1; }
}

.sda-item {
	margin: 1.1rem;
	padding: 1rem 1.2rem;
	border: 1px solid var(--bs-border-color);
	border-radius: 0.6rem;
	background-color: var(--bs-light-bg-subtle);
}

.sda-item .sda-idx {
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: 0.65rem;
	letter-spacing: 0.15em;
	color: #2A5F62;
}

[data-bs-theme="dark"] .sda-item .sda-idx {
	color: #6fd6d0;
}

/* Each item animates itself as it crosses the scroller's viewport */
.sda-reveal {
	animation: sda-rise linear both;
	animation-timeline: view();
	animation-range: entry 0% entry 90%;
}

@keyframes sda-rise {
	from {
		opacity: 0.1;
		translate: 0 1.5rem;
	}
	to {
		opacity: 1;
		translate: 0 0;
	}
}

/* Fallback: without scroll timelines the items stay visible and
   demo-web-tech.js drives the bar width instead */
@supports not (animation-timeline: scroll()) {
	.sda-progress i {
		animation: none;
	}

	.sda-reveal {
		animation: none;
	}
}


/* ------------------------------------------------------------
   5. Demo 3 — OKLCH, @property and color-mix()
      One number (--demo-hue) generates the whole palette.
   ------------------------------------------------------------ */
.oklch-lab {
	--demo-accent: oklch(0.62 0.13 var(--demo-hue));
}

.oklch-chip {
	width: 100%;
	height: 72px;
	border-radius: 0.6rem;
	border: 1px solid var(--bs-border-color);
	background-color: var(--demo-accent);
	transition: background-color 0.15s linear;
}

/* Seven-step tint/shade ladder computed from the single accent */
.oklch-ladder {
	display: grid;
	grid-template-columns: repeat(7, 1fr);
	gap: 0.4rem;
	height: 56px;
}

.oklch-ladder i {
	border-radius: 0.4rem;
	border: 1px solid var(--bs-border-color);
}

.oklch-ladder i:nth-child(1) { background: color-mix(in oklch, var(--demo-accent), black 75%); }
.oklch-ladder i:nth-child(2) { background: color-mix(in oklch, var(--demo-accent), black 50%); }
.oklch-ladder i:nth-child(3) { background: color-mix(in oklch, var(--demo-accent), black 25%); }
.oklch-ladder i:nth-child(4) { background: var(--demo-accent); }
.oklch-ladder i:nth-child(5) { background: color-mix(in oklch, var(--demo-accent), white 25%); }
.oklch-ladder i:nth-child(6) { background: color-mix(in oklch, var(--demo-accent), white 50%); }
.oklch-ladder i:nth-child(7) { background: color-mix(in oklch, var(--demo-accent), white 75%); }

/* A themed component to prove the point */
.oklch-btn {
	border: none;
	border-radius: 999px;
	padding: 0.5rem 1.4rem;
	font-weight: 700;
	color: #fff;
	background-color: var(--demo-accent);
	transition: background-color 0.15s linear;
}


/* ------------------------------------------------------------
   6. Demo 4 — variable font playground
   ------------------------------------------------------------ */
.vf-specimen {
	font-family: "Roboto Flex", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
	font-size: clamp(2.4rem, 6.5vw, 4.2rem);
	line-height: 1.1;
	text-align: center;
	color: var(--bs-heading-color);
	font-variation-settings:
		"wght" var(--vf-wght, 700),
		"wdth" var(--vf-wdth, 100);
	user-select: none;
}

.vf-ctl {
	display: grid;
	gap: 0.4rem;
}

.vf-ctl label {
	display: flex;
	justify-content: space-between;
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: 0.68rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
}

.vf-ctl output {
	color: #2A5F62;
	font-weight: 700;
}

[data-bs-theme="dark"] .vf-ctl output {
	color: #6fd6d0;
}

.vf-controls {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: 1.2rem;
}


/* ------------------------------------------------------------
   7. Demo 5 — View Transitions API
   ------------------------------------------------------------ */
.vt-panel {
	border: 1px solid var(--bs-border-color);
	border-radius: 0.6rem;
	background-color: var(--bs-body-bg);
	padding: 1.4rem;
	min-height: 150px;
	margin-top: 1rem;
}

.vt-panel h3 {
	view-transition-name: demo-vt-title;
	font-size: 1.3rem;
}

/* Old title exits up, new title enters from below */
::view-transition-old(demo-vt-title) {
	animation: demo-vt-out 0.25s ease both;
}

::view-transition-new(demo-vt-title) {
	animation: demo-vt-in 0.3s 0.08s ease both;
}

@keyframes demo-vt-out {
	to {
		opacity: 0;
		translate: 0 -12px;
	}
}

@keyframes demo-vt-in {
	from {
		opacity: 0;
		translate: 0 14px;
	}
}


/* ------------------------------------------------------------
   8. Demo 6 — :has(), the parent selector
      No JavaScript changes these cards. The CSS below reads the
      state of the inputs inside them.
   ------------------------------------------------------------ */
.has-card {
	border: 1px solid var(--bs-border-color);
	border-radius: 0.6rem;
	background-color: var(--bs-body-bg);
	padding: 1.1rem 1.3rem;
	transition: border-color 0.3s ease, box-shadow 0.3s ease, translate 0.3s ease;
}

.has-card .has-state {
	margin-top: 0.6rem;
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: 0.62rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
}

/* Card containing a checked checkbox */
.has-card:has(input[type="checkbox"]:checked) {
	border-color: #2A5F62;
	box-shadow: 0 0 0 3px rgba(42, 95, 98, 0.18);
	translate: 0 -3px;
}

.has-card:has(input[type="checkbox"]:checked) .has-state {
	color: #2A5F62;
}

[data-bs-theme="dark"] .has-card:has(input[type="checkbox"]:checked) {
	border-color: #6fd6d0;
}

[data-bs-theme="dark"] .has-card:has(input[type="checkbox"]:checked) .has-state {
	color: #6fd6d0;
}

/* Card containing a valid / invalid email field */
.has-card:has(input[type="email"]:valid:not(:placeholder-shown)) {
	border-color: #198754;
}

.has-card:has(input[type="email"]:valid:not(:placeholder-shown)) .has-state {
	color: #198754;
}

.has-card:has(input[type="email"]:invalid:not(:placeholder-shown)) {
	border-color: #dc3545;
}

.has-card:has(input[type="email"]:invalid:not(:placeholder-shown)) .has-state {
	color: #dc3545;
}


/* ------------------------------------------------------------
   9. Demo 7 — container queries
      The dashed box is the container. Drag its bottom-right
      corner: the card inside responds to the BOX width, not
      the viewport width.
   ------------------------------------------------------------ */
.cq-box {
	container-type: inline-size;
	container-name: demobox;
	resize: horizontal;
	overflow: auto;
	min-width: 240px;
	max-width: 100%;
	width: 100%;
	border: 1px dashed var(--bs-secondary-color);
	border-radius: 0.6rem;
	padding: 0.9rem;
}

/* Layout 1 (narrow): stacked — the thumb is a full-width banner */
.cq-card {
	display: grid;
	grid-template-columns: 1fr;
	gap: 0.8rem;
	align-items: center;
	border: 1px solid var(--bs-border-color);
	border-radius: 0.6rem;
	background-color: var(--bs-body-bg);
	padding: 0.9rem;
}

.cq-card .cq-thumb {
	width: 100%;
	height: 56px;
	border-radius: 0.5rem;
	background: linear-gradient(135deg, #3d7f86, #2A5F62 55%, #1E4447);
}

/* Breakpoints owned by the component, not the page */

/* Layout 2 (≥320px): thumb moves beside the text */
@container demobox (min-width: 320px) {
	.cq-card {
		grid-template-columns: 76px 1fr;
	}

	.cq-card .cq-thumb {
		width: 76px;
		height: 76px;
	}
}

/* Layout 3 (≥440px): the thumb grows and crosses to the right */
@container demobox (min-width: 440px) {
	.cq-card {
		grid-template-columns: 1fr 104px;
		padding: 1.3rem;
	}

	.cq-card .cq-thumb {
		width: 104px;
		height: 104px;
		order: 2;
	}
}


/* ------------------------------------------------------------
   10. Demo 8 — live feature matrix
   ------------------------------------------------------------ */
.feat-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr));
	gap: 0.6rem;
}

.feat-btn {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	border: 1px solid var(--bs-border-color);
	border-radius: 0.5rem;
	background-color: var(--bs-body-bg);
	color: var(--bs-body-color);
	padding: 0.55rem 0.8rem;
	font-size: 0.8rem;
	text-align: left;
	cursor: pointer;
	transition: border-color 0.2s ease;
}

.feat-btn:hover,
.feat-btn:focus-visible {
	border-color: #2A5F62;
}

.feat-btn[aria-pressed="true"] {
	border-color: #2A5F62;
	box-shadow: 0 0 0 2px rgba(42, 95, 98, 0.25);
}

.feat-btn .feat-dot {
	flex-shrink: 0;
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background-color: #adb5bd;
}

.feat-btn.pass .feat-dot { background-color: #198754; }
.feat-btn.fail .feat-dot { background-color: #dc3545; }
.feat-btn.fail { opacity: 0.65; }


/* ------------------------------------------------------------
   10. Demo 9 — text-wrap and drop caps
   ------------------------------------------------------------ */
.wrap-toggle {
	display: flex;
	gap: 0.6rem;
	margin-bottom: 1.2rem;
}

.wrap-toggle button {
	flex: 1;
	border: 1px solid var(--bs-border-color);
	border-radius: 0.5rem;
	background-color: var(--bs-body-bg);
	color: var(--bs-body-color);
	padding: 0.6rem 1rem;
	font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	font-weight: 700;
	cursor: pointer;
	transition: all 0.25s ease;
}

.wrap-toggle button:hover {
	border-color: #2A5F62;
}

.wrap-toggle button.active {
	background-color: #2A5F62;
	border-color: #2A5F62;
	color: #fff;
}

[data-bs-theme="dark"] .wrap-toggle button.active {
	background-color: #6fd6d0;
	color: #0a0a0a;
}

.wrap-demo {
	font-size: 1.05rem;
	line-height: 1.5;
	text-wrap: wrap;
}

.dropcap-para {
	max-width: 72ch;
	color: var(--bs-body-color);
	font-size: 1rem;
	line-height: 1.7;
}

.dropcap-para::first-letter {
	font-family: "Roboto Flex", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
	font-size: 3.8em;
	initial-letter: 3.8;
	font-weight: 900;
	font-variation-settings: "wdth" 75;
	color: #2A5F62;
}

[data-bs-theme="dark"] .dropcap-para::first-letter {
	color: #6fd6d0;
}

.dropcap-spec {
	--dc-wght: 700;
	--dc-wdth: 75;
	max-width: 72ch;
	color: var(--bs-body-color);
	font-size: 1rem;
	line-height: 1.7;
}

/* JS cannot style a ::first-letter pseudo-element directly,
   so the sliders write the custom properties above and this
   rule reads them */
.dropcap-spec::first-letter {
	font-family: "Roboto Flex", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
	font-size: 3.8em;
	initial-letter: 3.8;
	margin-right: 0.12em;
	font-variation-settings:
		"wght" var(--dc-wght),
		"wdth" var(--dc-wdth);
	color: #2A5F62;
}

[data-bs-theme="dark"] .dropcap-spec::first-letter {
	color: #6fd6d0;
}

.dc-controls {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: 1.5rem;
}

.dc-ctl {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.dc-ctl label {
	font-size: 0.9rem;
	font-weight: 500;
	color: var(--bs-body-color);
}

.dc-ctl output {
	font-weight: 600;
	color: #2A5F62;
	font-family: monospace;
	font-size: 0.95rem;
}

[data-bs-theme="dark"] .dc-ctl output {
	color: #6fd6d0;
}


/* ------------------------------------------------------------
   11. Reduced motion — kill the decorative movement
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
	.sda-reveal,
	.demo-code .live.flash {
		animation: none;
	}

	::view-transition-old(demo-vt-title),
	::view-transition-new(demo-vt-title) {
		animation: none;
	}
}
