@font-face {
  font-family: 'Outfit';
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url('../fonts/outfit-regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Outfit';
  font-weight: 900;
  font-style: normal;
  font-display: swap;
  src: url('../fonts/outfit-black.woff2') format('woff2');
}

:root {
  --red: #ed1c24;
  --red-soft: #ff5a60;
  --ink: #fff;
  --ink-2: rgba(255, 255, 255, 0.78);
  --ink-3: rgba(255, 255, 255, 0.52);
  --glass: rgba(16, 16, 18, 0.5);
  --glass-strong: rgba(12, 12, 14, 0.62);
  --hair: rgba(255, 255, 255, 0.14);
  --ease: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --app-h: 100dvh;
  --vv-top: 0px;
  --gutter: max(22px, env(safe-area-inset-left), env(safe-area-inset-right));
  color-scheme: dark;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
  background: #000;
  color: var(--ink);
  overscroll-behavior: none;
  touch-action: manipulation;
  overflow: hidden;
  width: 100%;
  max-width: 100%;
}

body {
  font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
}

button {
  font: inherit;
  color: inherit;
}

:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Background: poster paints instantly, video fades over it ---------- */
.bg {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--full-h, 100lvh);
  background: #000 url('../media/bg-poster.webp') center / cover no-repeat;
  opacity: 0;
  transition: opacity 2.4s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.bg.on {
  opacity: 1;
}
.bg video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1.2s var(--ease-out);
}
.bg video.on {
  opacity: 1;
}

.scrim {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--full-h, 100lvh);
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.3) 0%,
    rgba(0, 0, 0, 0) 24%,
    rgba(0, 0, 0, 0.12) 42%,
    rgba(0, 0, 0, 0.6) 64%,
    rgba(0, 0, 0, 0.82) 100%
  );
}

/* ---------- App frame ---------- */
/* absolute, not fixed: a fixed element would isolate its children, and the
   logo animations need to Screen-blend straight onto the background video.
   The document never scrolls, so it behaves exactly like fixed. */
.app {
  position: absolute;
  /* clip at the screen edges: the enlarged intro logos and the sideways screen
     slides must never make the page wider than the phone (that let Android
     scroll sideways and threw off the centring). clip, not hidden: it creates
     no scroll area, and neither isolates the logos Screen blend. */
  overflow: hidden;
  overflow: clip;
  left: 0;
  right: 0;
  top: var(--vv-top);
  height: var(--app-h);
  display: flex;
  justify-content: center;
  padding: 0 var(--gutter);
}
.col {
  position: relative;
  width: 100%;
  max-width: 440px;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* ---------- Brand lockup (proportions from the reference frame) ---------- */
.brand {
  /* logo width and top offset drive the whole lockup (and the back button) */
  --logo-w: min(46.7vw, calc(var(--app-h) * 0.263), 300px);
  --pad-top: max(calc(env(safe-area-inset-top) + 14px), calc(var(--app-h) * 0.066));
  position: relative;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: var(--pad-top);
  gap: calc(var(--app-h) * 0.028);
}
.logo-ooredoo svg,
.logo-22 svg {
  display: block;
  width: 100%;
  height: auto;
}
.logo-ooredoo {
  width: var(--logo-w);
}
.logo-22 {
  width: calc(var(--logo-w) * 0.439);
}
/* Logos stay hidden until the opening sequence (introBrand in flow.js)
   reveals them; once it ends, .in keeps them visible. Screen blending makes
   the black of the animation videos disappear into the background. */
.logo-ooredoo,
.logo-22 {
  position: relative;
  opacity: 0;
  mix-blend-mode: screen;
}
.brand.in .logo-ooredoo,
.brand.in .logo-22,
.brand.anim .logo-ooredoo,
.brand.anim .logo-22 {
  opacity: 1;
}
.logo-anim {
  position: absolute;
  left: 0;
  top: 0;
  max-width: none;
  pointer-events: none;
  opacity: 0;
}
.brand.anim .logo-anim {
  opacity: 1;
}
.brand.anim .logo-ooredoo svg,
.brand.anim .logo-22 svg {
  opacity: 0;
}
.brand.in .logo-anim {
  display: none;
}
/* At rest the logos are the animations own last frame, frozen into a canvas
   with black turned transparent (see freezeFrame in flow.js): same pixels as
   the video, and no blending, so the page never recomposites around them. */
.logo-frame {
  position: absolute;
  left: 0;
  top: 0;
  max-width: none;
  pointer-events: none;
}
.brand.vfinal .logo-anim {
  display: none;
}
.brand.vfinal .logo-ooredoo,
.brand.vfinal .logo-22 {
  mix-blend-mode: normal;
}
/* fallback if the frame could not be copied: keep the paused video itself */
.brand.vhold .logo-anim {
  display: block;
  opacity: 1;
}
.brand.vhold .logo-ooredoo svg,
.brand.vhold .logo-22 svg {
  opacity: 0;
}
.brand.vfinal .logo-ooredoo svg,
.brand.vfinal .logo-22 svg {
  opacity: 0;
}

/* keyboard open: the lockup steps back to give the field room */
body.kb .brand {
  --logo-w: min(26vw, 120px);
  --pad-top: max(calc(env(safe-area-inset-top) + 18px), 26px);
  gap: 0;
}
/* while typing, the badge steps aside: every pixel goes to the field */
body.kb .logo-22 {
  display: none;
}
body.kb .title {
  font-size: clamp(24px, 6.6vw, 30px);
  margin-top: 0;
}
body.kb .stage {
  margin-top: 4px;
}
body.kb .hint:empty {
  min-height: 0;
  margin: 0;
}

/* Back: small liquid-glass disc, centred on the x-height of the Ooredoo
   wordmark (0.123 of the logo width from its top edge). */
.back {
  --size: 40px;
  position: absolute;
  left: 0;
  top: calc(var(--pad-top) + var(--logo-w) * 0.123 - var(--size) / 2);
  width: var(--size);
  height: var(--size);
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: rgba(255, 255, 255, 0.72);
  background:
    linear-gradient(to bottom, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0) 70%),
    rgba(255, 255, 255, 0.05);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  box-shadow: none;
  display: grid;
  place-items: center;
  cursor: pointer;
  opacity: 0;
  transform: scale(0.86);
  pointer-events: none;
  transition:
    opacity 0.35s var(--ease),
    transform 0.45s var(--ease);
  z-index: 2;
}
.back .chev {
  display: block;
  width: 10px;
  height: 17px;
  margin-left: -2px; /* optical centring: a chevron's mass sits on its point */
}
.back.show {
  opacity: 0.85;
  transform: none;
  pointer-events: auto;
}
.back.show:active {
  opacity: 1;
  transform: scale(0.9);
  transition-duration: 0.1s;
}

/* ---------- Screens ---------- */
.stage {
  flex: 1;
  min-height: 0;
  display: grid;
  margin-top: 12px;
}
.screen {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  visibility: hidden;
}
.screen.active {
  visibility: visible;
}
.body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  padding: 8px 0 18px;
  /* no mask here: a mask would stop the glass boxes inside from blurring
     the background */
}
.body::-webkit-scrollbar {
  display: none;
}
/* Content sits in the optical middle of the free space (a little above true
   center), never parked against the button. The spacers collapse to zero
   when the content needs the room. */
.body::before,
.body::after {
  content: '';
  flex: 1 1 0;
  min-height: 0;
}
.body::after {
  flex-grow: 1.6;
}

.actions {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  padding-bottom: max(env(safe-area-inset-bottom), 14px);
}
body.kb .actions {
  padding-bottom: 10px;
}
body.kb .actions .link,
body.kb .actions .sig,
body.kb [data-kb-hide] {
  display: none;
}
body.kb [data-kb-hide] + * {
  margin-top: 0;
}

/* ---------- Type ---------- */
.eyebrow {
  margin: 0;
  font-size: 12px;
  line-height: 1.2;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}
.title {
  margin: 14px 0 0;
  font-weight: 900;
  font-size: clamp(30px, 8.6vw, 42px);
  line-height: 0.98;
  letter-spacing: -0.012em;
  text-transform: uppercase;
  text-wrap: balance;
}
.lead {
  margin: 14px 0 0;
  font-size: 17px;
  line-height: 1.45;
  color: var(--ink-2);
  text-wrap: pretty;
}

.lead.q {
  font-size: 19px;
  line-height: 1.4;
  color: var(--ink);
}
body.kb .lead.q {
  font-size: 17px;
}
.note-line {
  margin: 18px 0 0;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--ink-3);
}

/* progress: one thin segment per question, the current one fills on arrival */
.steps {
  display: flex;
  gap: 6px;
  margin-bottom: 18px;
}
.steps i {
  position: relative;
  flex: 1;
  height: 3px;
  border-radius: 2px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.18);
}
.steps i::after {
  content: '';
  position: absolute;
  inset: 0;
  background: #fff;
  transform: scaleX(0);
  transform-origin: left;
}
.steps i.done::after {
  transform: none;
}
.steps i.now::after {
  transition: transform 0.8s var(--ease) 0.3s;
}
body.kb .steps {
  margin-bottom: 12px;
}

/* ---------- Glass groups (iOS inset grouped list) ---------- */
.group {
  margin-top: 22px;
  border-radius: 18px;
  background: rgba(16, 16, 18, 0.42);
  /* frosted glass: softly blurs the background behind the box */
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  backdrop-filter: blur(12px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 12px 32px rgba(0, 0, 0, 0.35);
  overflow: hidden;
}
.row {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 56px;
  padding: 0 16px;
  transition: background 0.25s var(--ease);
}
.row + .row::before {
  content: '';
  position: absolute;
  top: 0;
  left: 16px;
  right: 0;
  height: 1px;
  background: var(--hair);
  transform: scaleY(0.5);
  transform-origin: top;
}
.row:focus-within {
  background: rgba(255, 255, 255, 0.05);
}
.row.invalid {
  background: rgba(237, 28, 36, 0.12);
}
.row input,
.row textarea.single {
  flex: 1;
  min-width: 0;
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  padding: 16px 0;
  outline: none;
  caret-color: var(--red);
}
/* single-line textarea used for names (Chrome offers no autofill strip on
   textareas, so the keyboard height never jumps while switching fields) */
.row textarea.single {
  display: block;
  resize: none;
  overflow: hidden;
  white-space: pre;
  line-height: 1.3;
  height: calc(17px * 1.3 + 32px);
}
::placeholder {
  color: rgba(255, 255, 255, 0.4);
  opacity: 1;
}
.hint {
  margin: 8px 4px 0;
  min-height: 1.4em;
  font-size: 13px;
  line-height: 1.4;
  color: var(--red-soft);
}

.note {
  padding: 14px 16px 12px;
}
.note textarea {
  display: block;
  width: 100%;
  min-height: calc(17px * 1.45 * 2);
  resize: none;
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  line-height: 1.45;
  outline: none;
  overflow: hidden;
  caret-color: var(--red);
  transition: height 0.24s var(--ease);
}
.meta {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: 8px 4px 0;
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-3);
}
.meta .count {
  font-variant-numeric: tabular-nums;
  transition: color 0.25s;
}
.meta .count.warn {
  color: var(--red-soft);
}

/* consent row with an iOS switch */
.switch-row {
  gap: 14px;
  padding: 14px 16px;
  cursor: pointer;
}
.switch-row span {
  flex: 1;
  font-size: 15px;
  line-height: 1.38;
  color: var(--ink-2);
}
input[role='switch'] {
  flex: none;
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  width: 51px;
  height: 31px;
  margin: 0;
  border-radius: 999px;
  background: rgba(120, 120, 128, 0.4);
  cursor: pointer;
  transition: background 0.3s var(--ease);
}
input[role='switch']::before {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 27px;
  height: 27px;
  border-radius: 999px;
  background: #fff;
  box-shadow:
    0 3px 8px rgba(0, 0, 0, 0.25),
    0 1px 1px rgba(0, 0, 0, 0.12);
  transition:
    transform 0.38s var(--ease),
    width 0.2s var(--ease);
}
input[role='switch']:checked {
  background: var(--red);
}
input[role='switch']:checked::before {
  transform: translateX(20px);
}
input[role='switch']:active::before {
  width: 33px;
}
input[role='switch']:checked:active::before {
  transform: translateX(14px);
}
.foot {
  margin: 8px 4px 0;
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-3);
}

/* ---------- Buttons ---------- */
.btn {
  appearance: none;
  border: 0;
  height: 56px;
  border-radius: 999px;
  font-size: 17px;
  letter-spacing: 0.01em;
  background: #fff;
  color: #0b0b0c;
  cursor: pointer;
  touch-action: manipulation;
  transition:
    transform 0.12s ease-out,
    background 0.3s var(--ease),
    color 0.3s var(--ease);
}
.btn:active:not(:disabled) {
  transform: scale(0.97);
}
.btn:disabled {
  background: rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.42);
  cursor: default;
}
.link {
  appearance: none;
  border: 0;
  background: none;
  padding: 10px;
  font-size: 15px;
  color: var(--ink-2);
  cursor: pointer;
  touch-action: manipulation;
  transition: opacity 0.12s;
}
.link:active {
  opacity: 0.5;
}
.sig {
  margin: 6px 0 0;
  text-align: center;
  font-size: 11px;
  line-height: 1.4;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

/* ---------- Review list (page 1) ---------- */
.review {
  margin-top: 22px;
}
.rev {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 13px 14px 13px 16px;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  transition: background 0.2s var(--ease);
}
.rev + .rev::before {
  content: '';
  position: absolute;
  top: 0;
  left: 16px;
  right: 0;
  height: 1px;
  background: var(--hair);
  transform: scaleY(0.5);
  transform-origin: top;
}
.rev:active {
  background: rgba(255, 255, 255, 0.07);
}
.rev .txt {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.rev .k {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.rev .a {
  font-size: 16px;
  line-height: 1.38;
  color: var(--ink);
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.rev .go {
  flex: none;
  color: rgba(255, 255, 255, 0.35);
}

/* ---------- Review card ---------- */
.card {
  margin-top: 22px;
  padding: 22px 20px 20px;
  border-radius: 22px;
  background: var(--glass-strong);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  backdrop-filter: blur(12px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 18px 40px rgba(0, 0, 0, 0.4);
}
.quote {
  margin: 0;
  font-size: 19px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.quote::before {
  content: '«\202F';
}
.quote::after {
  content: '\202F»';
}
.who {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.who b {
  font-weight: 900;
  font-size: 15px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.who span {
  font-size: 13px;
  color: var(--ink-3);
}
.card-foot {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
}
.card-foot .link {
  padding: 8px 4px;
}

/* ---------- Slide to send ---------- */
.slide {
  position: relative;
  height: 64px;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.12);
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}
.slide .fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, #b5121a, var(--red));
  opacity: 0.35;
  transform: translate3d(-100%, 0, 0);
  will-change: transform;
}
.slide .label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 0 24px; /* centred in the whole pill */
  font-size: 17px;
  letter-spacing: 0.01em;
  color: transparent;
  background: linear-gradient(
      100deg,
      rgba(255, 255, 255, 0.5) 0%,
      rgba(255, 255, 255, 0.5) 40%,
      #fff 50%,
      rgba(255, 255, 255, 0.5) 60%,
      rgba(255, 255, 255, 0.5) 100%
    )
    0 0 / 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  animation: shimmer 3s linear infinite;
  pointer-events: none;
}
@keyframes shimmer {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: 0% 0;
  }
}
.slide .status {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 0 24px; /* centred in the whole pill */
  font-size: 17px;
  opacity: 0;
  transition: opacity 0.3s var(--ease);
  pointer-events: none;
}
.slide.busy .status,
.slide.done .status {
  opacity: 1;
}
.thumb {
  position: absolute;
  left: 4px;
  top: 3px;
  width: 56px;
  height: 56px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: grab;
  touch-action: none;
  will-change: transform;
}
.thumb:active {
  cursor: grabbing;
}
.thumb .knob {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #fff;
  color: #0b0b0c;
  display: grid;
  place-items: center;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  transition: transform 0.18s var(--ease);
}
.slide.pressed .knob {
  transform: scale(0.94);
  transition-duration: 0.08s;
}
.knob svg {
  grid-area: 1 / 1;
  transition:
    opacity 0.25s var(--ease),
    transform 0.35s var(--ease);
}
.knob .spin,
.knob .check {
  opacity: 0;
  transform: scale(0.6);
}
.slide.busy .knob .arrow,
.slide.done .knob .arrow {
  opacity: 0;
  transform: scale(0.6);
}
.slide.busy .knob .spin {
  opacity: 1;
  transform: none;
  animation: spin 0.9s linear infinite;
}
.slide.done .knob .check {
  opacity: 1;
  transform: none;
}
@keyframes spin {
  to {
    rotate: 360deg;
  }
}
.slide-error {
  margin: 8px 4px 0;
  min-height: 1.4em;
  font-size: 13px;
  line-height: 1.4;
  text-align: center;
  color: var(--red-soft);
}

/* ---------- Preferences ---------- */
@media (prefers-reduced-motion: reduce) {
  .slide .label {
    animation: none;
    color: rgba(255, 255, 255, 0.75);
    background: none;
  }
  .note textarea {
    transition: none;
  }
}
@media (prefers-reduced-transparency: reduce) {
  .group,
  .card,
  .back,
  .slide {
    background: rgba(18, 18, 20, 0.94);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
@media (prefers-contrast: more) {
  .group,
  .card,
  .slide {
    background: rgba(8, 8, 10, 0.96);
    border-color: rgba(255, 255, 255, 0.5);
  }
  .lead,
  .switch-row span,
  .foot,
  .meta {
    color: #fff;
  }
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .group,
  .card,
  .back,
  .slide {
    background: rgba(18, 18, 20, 0.88);
  }
}

/* Text-only screens (confirmations, closing messages): centred column */
.screen.centered .body {
  align-items: center;
  text-align: center;
}
.screen.centered .lead {
  max-width: 32ch;
  text-wrap: balance;
}

/* Fading copy of an element that just left the layout (see morph in flow.js) */
.ghost {
  display: block !important;
  opacity: 1;
  filter: none !important;
  transition: none !important;
}
.ghost svg {
  opacity: 1 !important;
}
.ghost .logo-anim,
.ghost .logo-frame {
  display: none !important;
}

/* Labels behave like app chrome: no accidental selection or callouts */
.brand,
.eyebrow,
.title,
.lead,
.actions,
.meta,
.foot,
.note-line,
.rev,
.switch-row span {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
body.morphing .screen.active .body {
  overflow: visible;
  -webkit-mask-image: none;
  mask-image: none;
}
/* a screen leaving while the keyboard closes keeps its typing layout */
.screen.kb-frozen [data-kb-hide],
.screen.kb-frozen .actions .link,
.screen.kb-frozen .actions .sig {
  display: none;
}
.screen.kb-frozen .title {
  font-size: clamp(24px, 6.6vw, 30px);
  margin-top: 0;
}

/* Stable layers. While a screen is shown, the parts that move (stagger
   items) and the parts that fade (.fp) keep their own compositing layer.
   Without this the phone re-renders text the moment an animation ends,
   which nudges it by a fraction of a pixel: the one-frame twitch.
   Only transform and opacity are hinted, never on an ancestor of a glass
   box with opacity, so the frosted blur keeps working. */
.screen.active {
  will-change: transform;
}
.screen.active [data-stagger] {
  will-change: transform;
}
.screen.active .fp {
  will-change: opacity;
}
.screen.active [data-stagger].fp {
  will-change: transform, opacity;
}

/* text-only screens: the lock line centres with the rest */
.screen.centered .note-line {
  justify-content: center;
}

/* ---------- CP portrait (confirmation screens) ---------- */
.portrait {
  position: relative;
  /* about half the screen width, capped on short screens so it always fits */
  width: min(50vw, calc(var(--app-h) * 0.27), 230px);
  aspect-ratio: 1;
  margin: 0 auto 26px;
  flex: none;
}
.portrait img {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.55);
}
/* soft red halo behind the portrait: blooms in once, then breathes slowly */
.portrait-glow {
  position: absolute;
  inset: -24%;
  pointer-events: none;
}
.portrait-glow span {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(237, 28, 36, 0.36), rgba(237, 28, 36, 0.12) 58%, rgba(237, 28, 36, 0) 100%);
  animation: portrait-breathe 7s ease-in-out infinite;
}
@keyframes portrait-breathe {
  0%,
  100% {
    opacity: 0.72;
    transform: scale(0.97);
  }
  50% {
    opacity: 1;
    transform: scale(1.03);
  }
}
@media (prefers-reduced-motion: reduce) {
  .portrait-glow span {
    animation: none;
  }
}
body.kb .portrait {
  display: none;
}
