/* =======================================================================
   CELUS - OAuth consent screen (login-oauth-grant.ftl)
   Built on the CELUS Design System (light theme) + a celus.io brand panel.

   SCOPING
   -------
   `styles` in theme.properties loads every stylesheet on every login page, so
   nothing here may be global. Two consequences, both deliberate:

   - Every selector sits under `.oauth-grant`, the body class this page sets and
     no other page does. The design tokens live on that element rather than on
     `:root`, so names as generic as `--color-primary` cannot collide with
     login.css (which has its own, differently named, set).
   - `html.oauth-grant-html, body.oauth-grant` carries the page reset. The
     PatternFly stylesheets in `stylesCommon` set unscoped `html`/`body` rules
     that would otherwise win by document order, and a class selector out-
     specifies a bare element one.

   This page deliberately does NOT set `kcHtmlClass` (`login-pf`): login.css
   hangs its own body and card layout off it, and the consent screen is a
   full-bleed two column page rather than a centred card.

   THE RIGHT COLUMN IS A FLAT FRAME, NOT A CARD
   --------------------------------------------
   Per the design: no card chrome, no inner scroller. The column itself is the
   white surface, the content is a 440px measure centred in it, and the
   decision, the permission list and the small print are separated by hairlines
   rather than by boxes. That follows the convention the established consent
   screens share (GitLab's doorkeeper view, Gitea's grant template, Auth0's
   guidance):

   - the ask is centred, the permission list is NOT - it is left aligned so
     there is one edge to scan down;
   - one row per scope, a bold label and its own description, no icon tiles and
     no highlighted "main" row: on a page listing five things a user is granting,
     colour on one of them reads as decoration, not as meaning;
   - the signed-in row is an inline row between hairlines, not a bordered card;
   - the redirect disclosure is small print under the buttons, not a coloured
     alert;
   - accent colour belongs to the primary action alone.

   ICONS
   -----
   Inline SVG (Material Symbols, Apache-2.0) rendered by the `icon` macro in the
   template, not an icon font. The theme already pulls an icon font from a CDN
   for `<i>` elements, but a font that fails to load on the one page where the
   user makes a security decision would leave the page's affordances unlabelled,
   and Material Symbols is not among the fonts this theme ships. `.ms` therefore
   sizes an SVG child off `font-size`, so the DS icon scale still applies.
   ======================================================================= */

.oauth-grant {
  /* Brand */
  --color-primary:          #3a5afe;
  --color-primary-hover:    #6383ff;
  --color-primary-active:   #273fd9;
  --color-primary-bg:       #f0f5ff;
  --color-primary-bg-hover: #dee8ff;
  --color-primary-border:   #b5c9ff;

  /* Text */
  --color-text-heading:   #121212;
  --color-text-base:      #121212;
  --color-text-secondary: #4d4d4d;
  --color-text-tertiary:  #808080;

  /* Surfaces */
  --color-bg-container: #ffffff;
  --color-bg-layout:    #fafafa;

  /* Borders */
  --color-border:           #cdcdcd;
  --color-border-secondary: #e6e6e6;
  --color-split:            #f0f0f0;

  /* Semantic */
  --color-info:       #0b74f5;
  --color-info-bg:    #e6f5ff;
  --color-info-bd:    #85c8ff;
  --color-warning-bg: #fffae6;
  --color-warning-bd: #ffde85;
  --color-warning-fg: #cf7c00;

  /* Radius */
  --radius-sm: 6px;
  --radius:    8px;
  --radius-lg: 12px;
  --radius-xl: 16px;

  /* Brand panel */
  --brand-bg:   #0a0a0c;
  --brand-bg-2: #101018;
}

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

html.oauth-grant-html,
body.oauth-grant {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: 'Open Sans', system-ui, -apple-system, sans-serif;
  font-size: 14px;
  line-height: 22px;
  color: var(--color-text-base);
  background: var(--color-bg-container);
  -webkit-font-smoothing: antialiased;
}

.oauth-grant a { color: #0056cf; text-decoration: none; }
.oauth-grant a:hover { color: var(--color-primary-hover); }

.oauth-grant .ms {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  line-height: 1;
}
.oauth-grant .ms > svg {
  width: 1em;
  height: 1em;
  fill: currentColor;
  display: block;
}
.oauth-grant .ms--xs { font-size: 12px; }
.oauth-grant .ms--s  { font-size: 14px; }
.oauth-grant .ms--m  { font-size: 16px; }
.oauth-grant .ms--l  { font-size: 18px; }
.oauth-grant .ms--xl { font-size: 24px; }

/* The redirect URI in the small print: inline, so it sits inside the sentence
   rather than breaking it into a block. */
.oauth-grant .mono {
  display: inline;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 20px;
  color: var(--color-text-secondary);
  background: var(--color-split);
  border-radius: var(--radius-sm);
  padding: 1px 4px;
  overflow-wrap: anywhere;
  word-break: normal;
}

/* ======================= SHELL ======================= */

/* Single column below LG - the brand panel is decorative, so it is simply not
   rendered rather than stacked above the decision. */
.oauth-grant .auth-shell {
  display: grid;
  grid-template-columns: 1fr;
  min-height: 100vh;
}

.oauth-grant .brand-panel { display: none; }

/* ======================= CONSENT COLUMN ======================= */

.oauth-grant .consent-area {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--color-bg-container);
}

/* Safety net, not a scroller: at the design's viewport nothing overflows, so no
   scrollbar appears. It engages only if the content grows (a longer client name,
   more scopes) - clipping that would be worse than scrolling it. */
.oauth-grant .consent-scroll {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 16px;
  overflow-y: auto;
}

.oauth-grant .consent-card {
  width: 100%;
  max-width: 440px;
  display: flex;
  flex-direction: column;
}

.oauth-grant .consent-body { min-width: 0; }

/* ---- connection visual ---- */

.oauth-grant .conn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-bottom: 16px;
}

.oauth-grant .conn-node {
  height: 28px;
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.oauth-grant .conn-node--client {
  width: 28px;
  color: var(--color-primary);
}

.oauth-grant .conn-node--celus { padding: 0; }
.oauth-grant .conn-logo { display: block; height: 22px; width: auto; }

.oauth-grant .conn-link { display: flex; align-items: center; gap: 4px; }
.oauth-grant .conn-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--color-primary);
  opacity: .35;
  animation: kc-oauth-connflow 1.4s ease-in-out infinite;
}
.oauth-grant .conn-dot:nth-child(2) { animation-delay: .18s; }
.oauth-grant .conn-dot:nth-child(3) { animation-delay: .36s; }

@keyframes kc-oauth-connflow {
  0%, 100% { opacity: .25; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.4); }
}
@media (prefers-reduced-motion: reduce) {
  .oauth-grant .conn-dot { animation: none; opacity: .6; }
}

/* ---- head ---- */

.oauth-grant .consent-head { text-align: center; margin-bottom: 24px; }

.oauth-grant .consent-title {
  margin: 6px 0 0;
  font-size: 20px;
  line-height: 28px;
  font-weight: 600;
  color: var(--color-text-heading);
}

.oauth-grant .consent-desc {
  margin: 8px 0 0;
  font-size: 14px;
  line-height: 22px;
  color: var(--color-text-secondary);
}
.oauth-grant .consent-desc strong { font-weight: 600; color: var(--color-text-base); }

/* Deliberate line breaks in the head, kept off below 420px where the first line
   no longer fits the column and natural reflow reads better than a forced break
   that orphans one word. */
.oauth-grant .lb { display: none; }
@media (min-width: 420px) {
  .oauth-grant .lb { display: inline; }
}

/* ---- account row: an inline row between hairlines, no box ----

   The design's row is avatar + name + email + "Not you?". Keycloak gives this
   page no identity at all (see the template header), so only the escape hatch
   and a truthful label are rendered. The row keeps the design's geometry, so
   dropping real values in later is a markup change and not a layout change. */

.oauth-grant .account-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  margin-bottom: 20px;
  border-top: 1px solid var(--color-split);
  border-bottom: 1px solid var(--color-split);
}

.oauth-grant .account-icon {
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: 999px;
  background: var(--color-split);
  color: var(--color-text-secondary);
  font-size: 14px;
}

.oauth-grant .account-meta {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 8px;
  min-width: 0;
  text-align: left;
}
.oauth-grant .account-name { font-size: 14px; color: var(--color-text-base); }

.oauth-grant .account-switch {
  font-size: 12px;
  flex: none;
  color: var(--color-text-tertiary);
  text-decoration: none;
}
.oauth-grant .account-switch:hover,
.oauth-grant .consent-legal a:hover {
  color: var(--color-text-base);
  text-decoration: underline;
}
.oauth-grant .consent-legal a { color: var(--color-text-tertiary); text-decoration: none; }

/* ---- scopes: a plain left-aligned list, spacing instead of rules ---- */

.oauth-grant .scopes { margin-bottom: 20px; }

.oauth-grant .scopes-title {
  margin: 0 0 12px;
  font-size: 12px;
  line-height: 20px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--color-text-tertiary);
  text-align: left;
}

.oauth-grant .scope-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.oauth-grant .scope {
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 10px;
}

/* Bullet as a pseudo-element rather than a native list marker: the row is a flex
   container, which suppresses markers, and this way the dot's size, colour and
   baseline are exact. The <ul>/<li> markup already carries the list semantics,
   so the dot is purely decorative.
   margin-top centres the 5px dot on the 22px label line: (22 - 5) / 2 ~ 8. */
.oauth-grant .scope::before {
  content: "";
  flex: none;
  width: 5px;
  height: 5px;
  margin-top: 8px;
  border-radius: 50%;
  background: var(--color-text-tertiary);
}

.oauth-grant .scope-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  min-width: 0;
  text-align: left;
}

.oauth-grant .scope-label {
  font-size: 14px;
  line-height: 22px;
  font-weight: 600;
  color: var(--color-text-base);
}

.oauth-grant .scope-hint {
  font-size: 12px;
  line-height: 20px;
  color: var(--color-text-secondary);
}

/* ---- buttons ---- */

.oauth-grant .consent-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  margin: 0;
}

.oauth-grant .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 4px 16px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 14px;
  line-height: 22px;
  font-weight: 400;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.oauth-grant .btn--lg { height: 40px; padding: 8px 20px; }

.oauth-grant .btn--primary {
  width: 100%;
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
  font-weight: 600;
}
.oauth-grant .btn--primary:hover  { background: var(--color-primary-active); border-color: var(--color-primary-active); }
.oauth-grant .btn--primary:active { background: #1727b3; border-color: #1727b3; }

.oauth-grant .btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-primary-bg-hover);
}

/* ---- Deny: the secondary action, rendered as clickable text ---- */

.oauth-grant .btn-deny {
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  padding: 0 8px;
  background: none;
  border: 0;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 14px;
  line-height: 22px;
  color: var(--color-text-secondary);
  text-decoration: none;
  cursor: pointer;
  transition: color .15s ease, background .15s ease;
}
.oauth-grant .btn-deny:hover  { color: var(--color-text-base); background: var(--color-split); }
.oauth-grant .btn-deny:active { color: var(--color-text-base); background: var(--color-border-secondary); }
.oauth-grant .btn-deny:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--color-primary-bg-hover); }

/* ---- footer: a hairline, the decision, then the small print ---- */

.oauth-grant .consent-footer {
  flex: none;
  padding: 16px 0 0;
  border-top: 1px solid var(--color-split);
}

.oauth-grant .consent-legal {
  margin: 10px 0 0;
  font-size: 12px;
  line-height: 20px;
  color: var(--color-text-tertiary);
  text-align: center;
}

/* ---- feedback (Keycloak's own message, e.g. a failed consent) ---- */

.oauth-grant .consent-message {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  margin-bottom: 20px;
  border: 1px solid;
  border-radius: var(--radius);
  font-size: 12px;
  line-height: 20px;
  color: var(--color-text-base);
}
.oauth-grant .consent-message--error   { background: #fdebec; border-color: #f7b1b2; }
.oauth-grant .consent-message--warning { background: var(--color-warning-bg); border-color: var(--color-warning-bd); }
.oauth-grant .consent-message--info    { background: var(--color-info-bg); border-color: var(--color-info-bd); }

/* ======================= >= LG : split layout ======================= */

@media (min-width: 1024px) {
  /* The brand panel is fixed; only the consent column can scroll. */
  html.oauth-grant-html,
  body.oauth-grant { height: 100%; overflow: hidden; }

  .oauth-grant .auth-shell {
    grid-template-columns: minmax(360px, 42%) 1fr;
    height: 100vh;
    min-height: 0;
  }

  /* The consent column comes first in the DOM, so keyboard and screen-reader
     users reach the decision before the brand copy; explicit grid placement puts
     the panel back on the left visually. */
  .oauth-grant .brand-panel  { grid-area: 1 / 1; }
  .oauth-grant .consent-area { grid-area: 1 / 2; height: 100vh; min-height: 0; }

  .oauth-grant .consent-scroll { padding: 32px 40px; }

  .oauth-grant .brand-panel {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 40px;
    overflow: hidden;
    background:
      radial-gradient(120% 90% at 15% 0%, var(--brand-bg-2) 0%, var(--brand-bg) 60%),
      var(--brand-bg);
    color: #fff;
  }

  /* celus.io style light beams */
  .oauth-grant .brand-beams {
    position: absolute;
    inset: -20% -40% auto -10%;
    height: 130%;
    pointer-events: none;
    background:
      linear-gradient(115deg, transparent 38%, rgba(58, 90, 254, .55) 44%, transparent 49%),
      linear-gradient(115deg, transparent 52%, rgba(99, 131, 255, .32) 57%, transparent 61%),
      linear-gradient(115deg, transparent 64%, rgba(58, 90, 254, .20) 68%, transparent 72%);
    filter: blur(22px);
    opacity: .9;
  }

  .oauth-grant .brand-top,
  .oauth-grant .brand-body,
  .oauth-grant .brand-foot { position: relative; z-index: 1; }

  .oauth-grant .brand-logo { display: block; height: 37px; width: auto; }

  .oauth-grant .brand-headline {
    margin: 0 0 16px;
    font-size: 38px;
    line-height: 46px;
    font-weight: 600;
    letter-spacing: -.01em;
  }
  .oauth-grant .brand-headline-light {
    font-weight: 300;
    color: rgba(255, 255, 255, .94);
  }

  .oauth-grant .brand-sub {
    margin: 0 0 32px;
    max-width: 44ch;
    font-size: 16px;
    line-height: 24px;
    color: rgba(255, 255, 255, .62);
  }

  .oauth-grant .brand-points {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  .oauth-grant .brand-points li {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 14px;
    line-height: 22px;
    color: rgba(255, 255, 255, .86);
  }
  .oauth-grant .brand-point-icon {
    width: 32px;
    height: 32px;
    flex: none;
    font-size: 16px;
    border-radius: var(--radius);
    background: rgba(58, 90, 254, .16);
    border: 1px solid rgba(99, 131, 255, .32);
    color: #8ca7ff;
  }

  .oauth-grant .brand-foot {
    font-size: 12px;
    line-height: 20px;
    color: rgba(255, 255, 255, .38);
  }
}

@media (min-width: 1440px) {
  .oauth-grant .auth-shell { grid-template-columns: minmax(480px, 44%) 1fr; }
  .oauth-grant .brand-panel { padding: 56px; }
}

/* ======================= < SM ======================= */

@media (max-width: 575px) {
  .oauth-grant .consent-scroll { padding: 24px 16px 32px; align-items: flex-start; }
  .oauth-grant .consent-title { font-size: 18px; line-height: 26px; }
}
