/* FiveRP — passport office (registration + sign in). Design system: /opt/fivem/server-data/CLAUDE.md Deliberately zero box-shadow on panels. CEF composites the shadow of a backdrop-filtered element as an opaque rectangle, which is what put a black square behind this panel in game. Depth here comes from blur, hairlines and inner highlights only. */ @font-face { font-family: 'Unbounded'; font-style: normal; font-weight: 300 800; font-display: block; src: url('fonts/unbounded-latin.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: 'Unbounded'; font-style: normal; font-weight: 300 800; font-display: block; src: url('fonts/unbounded-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } @font-face { font-family: 'Unbounded'; font-style: normal; font-weight: 300 800; font-display: block; src: url('fonts/unbounded-cyrillic.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } :root { --surface: rgba(255, 255, 255, 0.72); --panel: rgba(255, 255, 255, 0.80); --field-bg: rgba(0, 0, 0, 0.04); --field-bg-focus:#ffffff; --fg: #1d1d1f; --fg-secondary: #6e6e73; --fg-tertiary: #a1a1a6; --accent: #0071e3; --accent-strong: #0077ed; --accent-soft: rgba(0, 113, 227, 0.08); --ring: rgba(0, 113, 227, 0.18); --line: rgba(0, 0, 0, 0.06); --line-strong: rgba(0, 0, 0, 0.10); --hover: rgba(0, 0, 0, 0.04); --success: #34c759; --danger: #ff3b30; --radius-lg: 1.5rem; --radius-md: 1rem; --radius-sm: 0.7rem; /* passport ink */ --pp-navy: #10315e; --pp-label: #46719f; --pp-value: #14202f; --sans: 'Unbounded', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, 'Liberation Mono', 'DejaVu Sans Mono', monospace; --ease: cubic-bezier(0.25, 0.8, 0.25, 1); color-scheme: light; } * { box-sizing: border-box; margin: 0; padding: 0; } html, body { width: 100%; height: 100%; background: transparent; /* the game is behind this page */ overflow: hidden; font-family: var(--sans); letter-spacing: -0.005em; -webkit-font-smoothing: antialiased; } /* ------------------------------------------------------------------- stage */ .stage { position: fixed; inset: 0; display: grid; place-items: center; padding: 32px; opacity: 0; visibility: hidden; transition: opacity 460ms var(--ease), visibility 0s linear 460ms; /* Lightening only. Never darken the game to make the panel readable — that is what produced the grey box before. */ background: radial-gradient(90% 70% at 50% 50%, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0) 72%); } .stage.is-open { opacity: 1; visibility: visible; transition: opacity 460ms var(--ease), visibility 0s; } /* -------------------------------------------------------------------- slab */ .slab { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 520px; width: min(1080px, 94vw); background: var(--surface); border: 1px solid rgba(255, 255, 255, 0.55); border-radius: var(--radius-lg); overflow: hidden; transform: translateY(14px) scale(0.985); opacity: 0; transition: width 620ms var(--ease), grid-template-columns 620ms var(--ease), transform 620ms var(--ease), opacity 480ms var(--ease); } .stage.is-open .slab { transform: none; opacity: 1; } /* Signing in needs no passport — collapse to a single column. */ .slab[data-view="login"] { width: min(460px, 94vw); grid-template-columns: minmax(0, 1fr) 0px; } .slab[data-view="login"] .pane-card { opacity: 0; pointer-events: none; transform: translateX(24px); } .pane { min-width: 0; } .pane-form { padding: 40px 40px 34px; display: flex; flex-direction: column; } .pane-card { padding: 32px; display: flex; flex-direction: column; justify-content: center; gap: 14px; border-left: 1px solid var(--line); background: linear-gradient(180deg, rgba(255,255,255,0.34), rgba(255,255,255,0.14)); transition: opacity 420ms var(--ease), transform 620ms var(--ease); } /* ----------------------------------------------------------------- eyebrow */ .eyebrow { display: flex; align-items: center; gap: 9px; font-size: 10px; font-weight: 600; letter-spacing: 0.20em; text-transform: uppercase; color: var(--fg-tertiary); margin-bottom: 24px; } .eyebrow .dot { width: 3px; height: 3px; border-radius: 50%; background: currentColor; } /* -------------------------------------------------------------------- rail */ .rail { display: flex; align-items: center; gap: 12px; margin-bottom: 0; opacity: 0; height: 0; overflow: hidden; transition: opacity 360ms var(--ease); } /* Signing in has no steps, so the rail collapses margin and all. */ .slab[data-view="account"] .rail, .slab[data-view="identity"] .rail { opacity: 1; height: auto; margin-bottom: 30px; } .rail-step { display: flex; align-items: center; gap: 8px; } .rail-mark { position: relative; width: 11px; height: 11px; border-radius: 50%; border: 1.5px solid var(--line-strong); background: transparent; transition: background-color .3s var(--ease), border-color .3s var(--ease); } .rail-step.is-active .rail-mark { border-color: var(--accent); background: var(--accent); } .rail-step.is-done .rail-mark { border-color: var(--accent); background: var(--accent); } /* Done and active must not look identical — done gets a tick. */ .rail-step.is-done .rail-mark::after { content: ''; position: absolute; left: 2.4px; top: 1px; width: 3px; height: 5.5px; border: solid #fff; border-width: 0 1.5px 1.5px 0; transform: rotate(42deg); } .rail-label { font-size: 11px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-tertiary); transition: color .3s var(--ease); } .rail-step.is-active .rail-label, .rail-step.is-done .rail-label { color: var(--fg-secondary); } .rail-line { position: relative; flex: 1; height: 1.5px; border-radius: 2px; background: var(--line-strong); overflow: hidden; } .rail-line i { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--accent); transition: width 560ms var(--ease); } .rail-line i.is-full { width: 100%; } /* ------------------------------------------------------------------- views */ .view { display: none; flex-direction: column; } .view.is-current { display: flex; animation: viewIn .5s var(--ease) both; } @keyframes viewIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } } .title { font-size: 28px; font-weight: 700; letter-spacing: -0.035em; line-height: 1.1; color: var(--fg); margin-bottom: 8px; } .sub { font-size: 13.5px; font-weight: 400; line-height: 1.55; color: var(--fg-secondary); margin-bottom: 26px; } /* ------------------------------------------------------------------ fields */ .field { display: block; margin-bottom: 16px; } .label { display: block; font-size: 11px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-secondary); margin-bottom: 7px; } .field input { width: 100%; border-radius: var(--radius-md); padding: 13px 14px; font-family: var(--sans); font-size: 14.5px; font-weight: 400; letter-spacing: -0.005em; color: var(--fg); background: var(--field-bg); border: 1px solid transparent; outline: none; transition: background-color .2s, border-color .2s, box-shadow .2s; } .field input::placeholder { color: var(--fg-tertiary); } .field input:focus { background: var(--field-bg-focus); border-color: var(--accent); } .field input.is-bad { border-color: var(--danger); } .hint { display: block; margin-top: 7px; font-size: 11px; font-weight: 400; color: var(--fg-tertiary); } .row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; } .row .field { margin-bottom: 16px; } /* password strength */ .pwmeter { display: block; height: 3px; margin-top: 9px; border-radius: 2px; background: var(--line); opacity: 0; transition: opacity .25s ease; } .pwmeter.is-live { opacity: 1; } .pwmeter i { display: block; height: 100%; width: 0; border-radius: 2px; background: var(--danger); transition: width .3s var(--ease), background-color .3s ease; } .pwmeter[data-level="2"] i { background: #ff9f0a; } .pwmeter[data-level="3"] i { background: var(--success); } /* ------------------------------------------------------------------ notice */ .notice { font-size: 12.5px; font-weight: 400; line-height: 1.5; color: var(--danger); max-height: 0; opacity: 0; overflow: hidden; transition: max-height .3s var(--ease), opacity .3s ease, margin .3s var(--ease); } .notice.is-shown { max-height: 60px; opacity: 1; margin-bottom: 14px; } .notice.is-good { color: #1f8f3d; } /* ----------------------------------------------------------------- buttons */ .btn { position: relative; width: 100%; border: 0; border-radius: 999px; padding: 14px 24px; font-family: var(--sans); font-size: 14px; font-weight: 600; letter-spacing: -0.01em; color: #fff; cursor: pointer; background-image: linear-gradient(180deg, var(--accent-strong), var(--accent)); transition: filter .2s ease, transform .12s var(--ease), opacity .2s ease; } .btn:hover:not(:disabled) { filter: brightness(1.08); } .btn:active:not(:disabled) { transform: scale(0.978); } .btn:disabled { opacity: .55; cursor: default; } .btn.is-busy span { opacity: 0; } .btn.is-busy::after { content: ''; position: absolute; top: 50%; left: 50%; width: 16px; height: 16px; margin: -8px 0 0 -8px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.35); border-top-color: #fff; animation: spin .7s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .switch { margin-top: 18px; text-align: center; font-size: 12.5px; font-weight: 400; color: var(--fg-secondary); } .link { border: 0; background: none; padding: 0; font-family: var(--sans); font-size: 12.5px; font-weight: 600; letter-spacing: -0.01em; color: var(--accent); cursor: pointer; } .link:hover { text-decoration: underline; } /* ==================================================================== PASSPORT A United States passport data page. This is the one saturated object on the screen; the form beside it stays neutral so the document reads as the hero. */ .passport { position: relative; width: 100%; aspect-ratio: 125 / 88; /* ID-3, the real bio-page proportion */ border-radius: 12px; overflow: hidden; padding: 11px 15px 0; display: flex; flex-direction: column; color: var(--pp-value); background: radial-gradient(78% 66% at 16% 14%, rgba(255,255,255,0.92), rgba(255,255,255,0) 62%), linear-gradient(155deg, #f8fbff 0%, #e9f1fa 46%, #f5f1e7 100%); border: 1px solid rgba(16, 49, 94, 0.16); transition: transform 700ms var(--ease); } .passport.is-issued { transform: translateY(-3px); } /* Engine-turned security print. Three cheap repeating gradients read convincingly as guilloche at this scale. */ .pp-guilloche { position: absolute; inset: 0; pointer-events: none; opacity: .55; background: repeating-radial-gradient(circle at 20% 44%, rgba(16,49,94,.055) 0 1px, transparent 1px 7px), repeating-radial-gradient(circle at 80% 62%, rgba(16,49,94,.05) 0 1px, transparent 1px 9px), repeating-linear-gradient(58deg, rgba(16,49,94,.032) 0 1px, transparent 1px 6px); } /* Laminate glare that follows the cursor. */ .pp-sheen { position: absolute; inset: 0; pointer-events: none; opacity: .55; background: radial-gradient(circle at var(--mx, 78%) var(--my, 10%), rgba(255,255,255,0.75) 0%, rgba(255,255,255,0) 46%); transition: opacity .5s ease; } /* ------------------------------------------------------------ passport head */ .pp-head { position: relative; display: flex; align-items: center; gap: 10px; padding-bottom: 9px; border-bottom: 1px solid rgba(16, 49, 94, 0.18); } .pp-seal { flex: none; width: 30px; height: 30px; display: block; } .pp-seal svg { width: 100%; height: 100%; display: block; } .pp-seal .ring-out, .pp-seal .ring-in { fill: none; stroke: rgba(16,49,94,.55); stroke-width: 1.1; } .pp-seal .ring-in { stroke-width: .6; } .pp-seal .stars { fill: rgba(16,49,94,.6); } .pp-seal .shield-chief { fill: rgba(16,49,94,.75); } .pp-seal .shield-pales { fill: rgba(16,49,94,.28); } .pp-seal .shield-edge { fill: none; stroke: rgba(16,49,94,.65); stroke-width: 1.2; } .pp-head-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; } .pp-kind { font-size: 13px; font-weight: 700; letter-spacing: 0.30em; text-transform: uppercase; color: var(--pp-navy); } .pp-country { font-size: 8px; font-weight: 600; letter-spacing: 0.15em; text-transform: uppercase; color: var(--pp-label); } .pp-chip { margin-left: auto; width: 19px; height: 15px; opacity: .6; } .pp-chip svg { width: 100%; height: 100%; fill: none; stroke: rgba(16,49,94,.6); stroke-width: 1; } /* ------------------------------------------------------------ passport body */ .pp-body { position: relative; display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 12px; padding-top: 8px; } .pp-left { display: flex; flex-direction: column; gap: 9px; } .pp-photo { position: relative; align-self: start; border: 1px solid rgba(16, 49, 94, 0.22); border-radius: 3px; background: linear-gradient(180deg, #eef2f7, #dde5ee); aspect-ratio: 35 / 45; /* passport photo proportion */ overflow: hidden; display: grid; place-items: end center; } .pp-bust { width: 76%; height: 88%; align-self: end; } .pp-photo-label { position: absolute; top: 4px; left: 5px; font-size: 6px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(16, 49, 94, 0.42); } /* The secondary faded portrait real passports carry to the right of the data. */ .pp-ghost { position: absolute; right: 2px; top: 34%; width: 50px; opacity: .1; pointer-events: none; } .pp-ghost svg { width: 100%; display: block; fill: var(--pp-navy); } .pp-fields { display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px 10px; align-content: start; min-width: 0; } .pp-f { grid-column: span 2; min-width: 0; } .pp-f--type { grid-column: span 1; } .pp-f--code { grid-column: span 1; } .pp-f--no { grid-column: span 4; } .pp-f--wide { grid-column: span 6; } .pp-f dt { font-size: 6.5px; font-weight: 600; line-height: 1.35; letter-spacing: 0.13em; text-transform: uppercase; color: var(--pp-label); white-space: nowrap; } .pp-f dd { font-size: 10px; font-weight: 500; line-height: 1.3; letter-spacing: -0.01em; color: var(--pp-value); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .pp-f dd.mono { font-family: var(--mono); font-size: 10px; font-weight: 500; letter-spacing: 0.02em; } .pp-f--auth { grid-column: span 4; } .pp-f--auth dd { font-size: 8.5px; font-weight: 400; color: var(--pp-label); } /* The two fields the player actually controls — set larger than the rest. */ .pp-name { font-size: 15px !important; font-weight: 700 !important; line-height: 1.25 !important; letter-spacing: -0.02em !important; text-transform: uppercase; color: var(--pp-navy) !important; min-height: 19px; } .pp-name:empty::before { content: attr(data-empty); color: rgba(16, 49, 94, 0.25); } /* Each keystroke re-prints the value; the fade makes it feel typeset. */ .printed { display: inline-block; animation: printIn .4s var(--ease) both; } @keyframes printIn { from { opacity: 0; transform: translateY(3px); filter: blur(3px); } to { opacity: 1; transform: none; filter: blur(0); } } /* ----------------------------------------------------------------- signature */ .pp-sign { position: relative; display: flex; flex-direction: column; } .pp-sign-ink { font-family: 'Segoe Script', 'Bradley Hand', 'Snell Roundhand', cursive; font-size: 11px; color: rgba(16, 49, 94, 0.75); height: 14px; line-height: 14px; white-space: nowrap; overflow: hidden; transform: rotate(-1.5deg); transform-origin: left bottom; } .pp-sign-rule { height: 1px; background: rgba(16, 49, 94, 0.28); } .pp-sign-label { font-size: 6px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--pp-label); margin-top: 2px; } /* ----------------------------------------------------------------------- MRZ */ .pp-mrz { margin: 6px -15px 0; margin-top: auto; /* pinned to the foot of the page */ padding: 6px 15px 7px; border-top: 1px solid rgba(16, 49, 94, 0.18); background: rgba(255, 255, 255, 0.62); display: flex; flex-direction: column; gap: 2px; } .pp-mrz span { display: block; font-family: var(--mono); font-size: 10px; font-weight: 500; line-height: 1.25; letter-spacing: 0.055em; color: var(--pp-navy); white-space: nowrap; overflow: hidden; } /* --------------------------------------------------------------------- stamp */ .pp-stamp { position: absolute; right: 13px; bottom: 50px; display: flex; flex-direction: column; align-items: center; gap: 1px; padding: 7px 13px; border: 2px solid rgba(176, 42, 42, 0.62); border-radius: 4px; color: rgba(176, 42, 42, 0.78); /* multiply lets the guilloche show through, like real stamp ink */ mix-blend-mode: multiply; transform: rotate(-13deg) scale(1.5); opacity: 0; pointer-events: none; transition: opacity 420ms var(--ease), transform 520ms cubic-bezier(.2,1.4,.4,1); } .pp-stamp.is-stamped { opacity: 1; transform: rotate(-13deg) scale(1); } .pp-stamp-top, .pp-stamp-bot { font-size: 6.5px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; } .pp-stamp-mid { font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; } .pp-caption { text-align: center; font-size: 11px; font-weight: 400; color: var(--fg-tertiary); } /* ------------------------------------------------------------------- motion */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; } } :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; } ::selection { background: var(--accent-soft); color: var(--accent-strong); } /* ---------------------------------------------------------------- NUI final CEF turns backdrop-filter and box-shadow into opaque black plates at the element bounds, so both are gone from this file entirely. Panels earn their separation from opacity and hairlines instead of blur, which means the surface has to carry more white than it did when a blur sat behind it. Appended last so it wins over anything above. */ :root { --surface: rgba(255, 255, 255, 0.95); --panel: rgba(255, 255, 255, 0.97); } .slab { background: rgba(255, 255, 255, 0.95); border: 1px solid rgba(0, 0, 0, 0.08); } .stage { background: none; } .field:focus, .field:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; }