/* Inter, variable, served from here (fonts/, from @fontsource-variable/inter): Latin and Vietnamese, each loaded only
   when a page has its letters. */
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('fonts/inter-latin-wght-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('fonts/inter-vietnamese-wght-normal.woff2') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }

/* DatLab's ink and paper are the branding's (#293133 on #FBFBF9); a product brings its own colours to its card. */
:root {
	--paper: #fbfbf9;
	--ink: #293133;
	--muted: #5c6567;
	--line: rgb(41 49 51 / 0.12);
	--pop: #ffffff;
	--edge: rgb(0 0 0 / 0.28);
	--gutter: 24px;
	color-scheme: light;
}
@media (prefers-color-scheme: dark) {
	:root {
		--paper: #141819;
		--ink: #fbfbf9;
		--muted: #a7aeb0;
		--line: rgb(251 251 249 / 0.13);
		--pop: #242a2b;
		--edge: rgb(255 255 255 / 0.2);
		color-scheme: dark;
	}
}
@media (max-width: 600px) {
	:root { --gutter: 16px; }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
	margin: 0;
	background: var(--paper);
	color: var(--ink);
	font: 400 16px/1.6 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
	font-optical-sizing: auto;
	-webkit-font-smoothing: antialiased;
	/* Nothing may make the page scroll sideways; clip, unlike hidden, leaves sticky and scrolling alone. */
	overflow-x: clip;
}
a { color: inherit; }
.wrap { max-width: 1080px; margin: 0 auto; padding: 0 var(--gutter); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Sizes and spaces step by the golden ratio: 16, 26, 42, 68, 110, 178, 288 (each φ times the one before). A card is
   288; its mark, like the hero's, 178.
   The hero, as Panic's: no bar, only the mark, as the branding's sticker (dist/dl/sticker.svg, the favicon too), large
   and centred. */
.hero { padding: 68px 0 110px; }
.dl { display: block; width: 178px; height: 178px; margin: 0 auto; }

/* Products: one square card each, as Panic's app icons. */
.products h2 { margin: 0 0 26px; text-align: center; font-size: 16px; line-height: 16px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 288px)); justify-content: center; gap: 26px; }
/* Four products: one row when the screen is wide enough for four cards, else two by two, never three and one. */
.products.wrap { max-width: 1326px; }
@media (max-width: 1325px) and (min-width: 650px) {
	.grid:has(> .card:nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 288px)); }
}

/* Every card the same square: what is inside is sized by the card's width (cqi), so it always fits. The mark is
   1/φ of the card (178), and what is left is shared evenly above and below. */
.card {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	aspect-ratio: 1;
	border-radius: 9%;
	container-type: inline-size;
	text-align: center;
	transition: transform 0.25s ease;
}
.card:hover, .card:focus-within { z-index: 2; transform: translateY(-3px); }
/* A product's mark, as a die-cut sticker: white backing round its outline, a soft shadow under it. */
.sticker { display: block; width: 61.8cqi; height: auto; margin-bottom: 3.5cqi; overflow: visible; }
.card h3 { margin: 0; font-size: clamp(18px, 9cqi, 26px); line-height: 1.23; letter-spacing: -0.02em; font-weight: 700; }
/* Pointed at, a product's mark comes alive. Peek glances left, right and down, then blinks, over and over; its head
   and the head's white backing lean together, about the same point (in the view box's units: low on the head, a
   little left of its middle). */
.peek .head-g, .peek .head-back { transform-box: view-box; transform-origin: 242.6px 325px; }
.peek .lids { transform-box: fill-box; transform-origin: center; }
.card:hover .peek .head-g, .card:hover .peek .head-back { animation: peek-head 3.2s cubic-bezier(0.45, 0, 0.2, 1) infinite; }
.card:hover .peek .pupil { animation: peek-look 3.2s cubic-bezier(0.45, 0, 0.2, 1) infinite; }
.card:hover .peek .lids { animation: peek-blink 3.2s linear infinite; }
@keyframes peek-head {
	0%, 6% { transform: none; }
	16%, 30% { transform: rotate(-3deg); }
	40%, 54% { transform: rotate(3deg); }
	62%, 70% { transform: rotate(1deg); }
	78%, 100% { transform: none; }
}
@keyframes peek-look {
	0%, 6% { transform: none; }
	16%, 30% { transform: translate(-26.2px, 18.3px); }
	40%, 54% { transform: translate(26.2px, 18.3px); }
	62%, 70% { transform: translate(0, 41.9px); }
	78%, 100% { transform: none; }
}
@keyframes peek-blink {
	0%, 84%, 90%, 100% { transform: none; }
	87% { transform: scaleY(0.08); }
}
/* The words keep within the mark's width, so their edges are its edges. */
.card h3, .card > p { max-width: 61.8cqi; }
.card h3 a { text-decoration: none; }
/* A product sold on request: its name is a button that opens the contact popup, looking like the other names. */
.card h3 .open { padding: 0; border: 0; background: none; font: inherit; letter-spacing: inherit; color: inherit; cursor: pointer; }
/* The whole card is the link. */
.card h3 :is(a, .open)::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.card h3 :is(a, .open):focus-visible { outline: none; }
.card:has(h3 :is(a, .open):focus-visible) { outline: 3px solid var(--accent); outline-offset: 3px; }
.card > p { margin: 0.25em 0 0; font-size: clamp(13px, 5.55cqi, 16px); line-height: 1.375; color: var(--muted); text-wrap: balance; }

/* Pointed at, a product (or the DatLab sticker, or the footer's name) says more in a note, as Panic's: above it where
   the note fits whole, else beside it, else below (site.js sets data-side). Only with a pointer: on touch the card
   opens the product. */
.has-pop { position: relative; }
.brand { width: fit-content; margin: 0 auto; }
.pop {
	position: absolute;
	z-index: 2;
	width: 340px; /* a card and 26 either side */
	max-width: calc(100vw - 2 * var(--gutter));
	padding: 26px;
	border-radius: 16px;
	background: var(--pop);
	text-align: left;
	/* A hairline round the note and its arrow, and a soft shade under both. */
	filter: drop-shadow(0 0 0.5px var(--edge)) drop-shadow(0 10px 22px rgb(0 0 0 / 0.1));
	/* Hidden, a note is not laid out at all: a hidden one still in the layout pushed the page wider than a narrow
	   window and let it scroll sideways. It fades in from @starting-style and out before display goes. */
	display: none;
	opacity: 0;
	transform: var(--at) translate(var(--from)) scale(0.96);
	transform-origin: var(--origin);
	transition: opacity 0.14s ease, transform 0.14s ease, display 0.14s;
	transition-behavior: allow-discrete;
}
/* A short note (DatLab's own) is a card wide. */
.pop.small { width: 288px; }
.pop[data-side='top'] { left: 50%; bottom: calc(100% + 16px); --at: translateX(-50%); --from: 0, 8px; --origin: 50% 100%; }
.pop[data-side='bottom'] { left: 50%; top: calc(100% + 16px); --at: translateX(-50%); --from: 0, -8px; --origin: 50% 0; }
.pop[data-side='right'] { top: 50%; left: calc(100% + 16px); --at: translateY(-50%); --from: -8px, 0; --origin: 0 50%; }
.pop[data-side='left'] { top: 50%; right: calc(100% + 16px); --at: translateY(-50%); --from: 8px, 0; --origin: 100% 50%; }
/* It grows from its arrow with a little spring, and its sticker is slapped on its corner a moment later. */
@media (hover: hover) {
	.has-pop:hover > .pop, .has-pop:focus-within > .pop {
		display: block;
		opacity: 1;
		transform: var(--at);
		transition: opacity 0.2s ease 0.06s, transform 0.36s cubic-bezier(0.2, 0.9, 0.25, 1.1) 0.06s, display 0s;
		transition-behavior: allow-discrete;
	}
	@starting-style {
		.has-pop:hover > .pop, .has-pop:focus-within > .pop { opacity: 0; transform: var(--at) translate(var(--from)) scale(0.96); }
	}
	.has-pop:hover > .pop .tag, .has-pop:focus-within > .pop .tag { animation: stick 0.45s 0.16s cubic-bezier(0.3, 1.5, 0.5, 1) both; }
}
@keyframes stick { from { opacity: 0; transform: scale(1.6) rotate(-16deg); } }
/* The arrow on the side facing what it tells of, under the note's content; and a bridge the pointer crosses into the
   note. */
.pop::after { content: ''; position: absolute; z-index: -1; width: 16px; height: 16px; border-radius: 3px; background: var(--pop); transform: translate(-50%, -50%) rotate(45deg); }
.pop[data-side='top']::after { left: 50%; top: 100%; }
.pop[data-side='bottom']::after { left: 50%; top: 0; }
.pop[data-side='right']::after { left: 0; top: 50%; }
.pop[data-side='left']::after { left: 100%; top: 50%; }
.pop::before { content: ''; position: absolute; }
.pop[data-side='top']::before { left: 0; right: 0; top: 100%; height: 26px; }
.pop[data-side='bottom']::before { left: 0; right: 0; bottom: 100%; height: 26px; }
.pop[data-side='right']::before { top: 0; bottom: 0; right: 100%; width: 26px; }
.pop[data-side='left']::before { top: 0; bottom: 0; left: 100%; width: 26px; }
/* The sticker of what the note tells of, stuck on its top right corner, a little askew. */
.pop .tag { position: absolute; top: -20px; right: -16px; width: 58px; height: auto; transform: rotate(8deg); }
.pop b { display: block; padding-right: 36px; font-size: 26px; line-height: 1.2; letter-spacing: -0.025em; font-weight: 700; color: var(--accent, var(--ink)); }
.pop p { margin: 10px 0 0; font-size: 16px; line-height: 1.5; color: var(--muted); text-wrap: pretty; }
/* A real picture of the product, as wide as a card. */
.pop picture { display: block; margin-top: 16px; overflow: hidden; border: 1px solid var(--line); border-radius: 10px; }
.pop picture img { display: block; width: 100%; height: auto; }
.pop .where { margin-top: 10px; font-weight: 600; color: var(--ink); }
.pop :is(a, .go) { display: inline-block; border: 0; font-family: inherit; cursor: pointer; margin-top: 26px; padding: 10px 26px; border-radius: 999px; background: var(--ink); color: var(--paper); font-size: 16px; font-weight: 600; text-decoration: none; transition: background 0.15s ease; }
.pop :is(a, .go):hover { background: var(--accent); color: #fff; }

/* Pointed at, the duck bobs on its wave and rocks a little, about the bottom of the wave. */
.duck { width: 51.2cqi; transform-origin: 50% 92%; }
.card:hover .duck { animation: duck-bob 1.6s ease-in-out infinite; }
@keyframes duck-bob {
	0%, 100% { transform: translateY(0) rotate(0); }
	25% { transform: translateY(-2.5cqi) rotate(-3deg); }
	50% { transform: translateY(0) rotate(0); }
	75% { transform: translateY(-1.2cqi) rotate(2deg); }
}

/* Pointed at, CrHerd's marionette sways on its strings, about the top of the bar. */
.herd { transform-origin: 50% 8%; }
.card:hover .herd { animation: herd-sway 2.4s ease-in-out infinite; }
@keyframes herd-sway {
	0%, 100% { transform: rotate(0); }
	25% { transform: rotate(-4deg); }
	75% { transform: rotate(4deg); }
}

/* A product still being built: a small road-works barrier stands beside its name, a little askew, and its note says
   so in words. It takes no room in the line, so the name stays centred like the others. */
.works { position: absolute; height: 1.05em; width: auto; margin: 0.08em 0 0 0.3em; transform: rotate(8deg); transition: transform 0.4s cubic-bezier(0.3, 1.5, 0.5, 1); }
.card:hover .works { transform: rotate(-4deg) scale(1.06); }
.pop .soon { display: flex; align-items: center; gap: 8px; margin: 8px 0 0; font-size: 13px; font-weight: 600; color: var(--accent); }
.pop .soon img { flex: none; }
/* Pointed at, the ζ tilts a little, as if writing itself. */
.zed { transform-origin: 50% 50%; transition: transform 0.4s cubic-bezier(0.3, 1.5, 0.5, 1); }
.card:hover .zed { transform: rotate(-8deg) scale(1.03); }

/* Serpy: Peek's indigo. */
.serpy { --accent: #4f5bd5; }
@media (prefers-color-scheme: dark) {
	.serpy { --accent: #9aa3f5; }
}
/* Zeta: deep teal, the colour of data. */
.zeta { --accent: #0e7490; }
@media (prefers-color-scheme: dark) {
	.zeta { --accent: #67e8f9; }
}
/* CrHerd: its violet. */
.crherd { --accent: #7c3aed; }
@media (prefers-color-scheme: dark) {
	.crherd { --accent: #c4b5fd; }
}
/* Đua Vịt: the beak's orange, dark enough for text on white. */
.duavit { --accent: #c2410c; }
@media (prefers-color-scheme: dark) {
	.duavit { --accent: #fdba74; }
}

footer { margin-top: 110px; }
footer .wrap { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 10px; padding-bottom: 42px; font-size: 14px; line-height: 16px; color: var(--muted); }
.lang { display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
.lang:hover, .contact:hover { color: var(--ink); }
/* The footer's Contact: a button that reads as the link beside it. */
.contact { padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: pointer; }

/* The contact popup, as a product's note: the DatLab sticker on its corner, our email large, two buttons. */
.contact-box { position: fixed; width: min(340px, calc(100vw - 2 * var(--gutter))); padding: 26px; border: 0; border-radius: 16px; background: var(--pop); color: var(--ink); box-shadow: 0 0 0 1px var(--edge), 0 18px 42px rgb(0 0 0 / 0.18); overflow: visible; }
.contact-box:modal { overscroll-behavior: contain; }
.contact-box::backdrop { background: rgb(20 24 25 / 0.35); backdrop-filter: blur(3px); overflow: hidden; overscroll-behavior: contain; }
.contact-box .tag { position: absolute; top: -20px; left: -16px; width: 58px; height: auto; transform: rotate(-8deg); }
.contact-box h2 { padding-left: 34px; }
.contact-box h2 { margin: 0; font-size: 26px; line-height: 1.2; letter-spacing: -0.025em; font-weight: 700; }
.contact-box p { margin: 10px 0 0; font-size: 16px; line-height: 1.5; color: var(--muted); }
.contact-box .mail { display: block; margin: 6px 0 0; font-size: 20px; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.contact-box .actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; }
.contact-box .send, .contact-box .copy { display: inline-flex; align-items: center; gap: 8px; padding: 10px 22px; border-radius: 999px; font: inherit; font-size: 16px; font-weight: 600; text-decoration: none; cursor: pointer; transition: background 0.15s ease, color 0.15s ease; }
.contact-box .send { border: 0; background: var(--ink); color: var(--paper); }
.contact-box .copy { border: 1.5px solid var(--line); background: none; color: var(--ink); }
.contact-box .copy:hover { border-color: var(--ink); }
.contact-box .send .ico { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.contact-box .x { position: absolute; top: 12px; right: 12px; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%; background: none; font-size: 22px; line-height: 1; color: var(--muted); cursor: pointer; }
.contact-box .x:hover { background: var(--line); color: var(--ink); }
/* A product's note in a popup, on touch: the note's own content, laid out as it is on the card. */
/* Only its content scrolls, so the sticker on its corner is not cut off. */
.info-box { width: min(380px, calc(100vw - 2 * var(--gutter))); }
.info-box .body { max-height: calc(100dvh - 4 * var(--gutter) - 52px); overflow: auto; overscroll-behavior: contain; }
.info-box b { display: block; padding: 0 40px 0 34px; font-size: 26px; line-height: 1.2; letter-spacing: -0.025em; font-weight: 700; color: var(--accent, var(--ink)); }
.info-box picture { display: block; margin-top: 16px; overflow: hidden; border: 1px solid var(--line); border-radius: 10px; }
.info-box picture img { display: block; width: 100%; height: auto; }
.info-box .where { margin-top: 10px; font-weight: 600; color: var(--ink); }
.info-box .soon { display: flex; align-items: center; gap: 8px; margin: 8px 0 0; font-size: 13px; font-weight: 600; color: var(--accent); }
.info-box :is(a, .go) { display: inline-block; margin-top: 26px; padding: 10px 26px; border: 0; border-radius: 999px; background: var(--ink); color: var(--paper); font: inherit; font-size: 16px; font-weight: 600; text-decoration: none; cursor: pointer; }
.lang svg { flex: none; width: 21px; height: 14px; border-radius: 2px; box-shadow: 0 0 0 1px var(--line); }

@media (max-width: 600px) {
	.hero { padding: 42px 0 68px; }
	footer { margin-top: 68px; }
}
@media (prefers-reduced-motion: reduce) {
	.card, .pop { transition: none; }
	.card:hover .peek *, .card:hover .duck, .card:hover .herd { animation: none; }
	.zed, .works { transition: none; }
	.card:hover .zed { transform: none; }
	.card:hover .works { transform: rotate(9deg); }
}

/* The page for an address that is not here. */
.lost { display: grid; justify-items: center; align-content: center; gap: 10px; min-height: 100vh; padding-block: 68px; text-align: center; }
.lost img { display: block; width: 110px; height: 110px; margin-bottom: 16px; }
.lost h1 { margin: 0; font-size: 26px; line-height: 1.2; letter-spacing: -0.025em; }
.lost p { margin: 0; color: var(--muted); }
