{{-- Ellipses in distinct corner quadrants (TL/TR/BL/BR), max 4. Same logo aspect ratio & on-screen lean right (±45° when mirror flips X). @param bool $mirror Optional: flip decoration left↔right (default false). @param string $intensity 'default' | 'subtle' (default: subtle) @param bool $randomize false = fixed TL + BR pair (default: true) @param int $minEllipses 1–4 (default: 1) @param int $maxEllipses 1–4 (default: 2) @param string|null $layout Optional: 'centered' to pull shapes in toward content column (default: corner layout) Ellipse & gradient colors: when randomize, picks from --primary, --secondary, --accent --}} @php $colorTokens = ['primary', 'secondary', 'accent']; /** Logo oval proportions (tsic mark): wide, not skinny */ $logoRxRef = 40; $logoRyRef = 20; /** * Fixed ellipse size (no “big/small” per render). * ry is derived from rx so the ellipse shape stays identical. */ $shapeRxMin = 250; $shapeRxMax = 250; /** +45° in SVG; with mirror (scale -1 X) use -45° so both read “เอียงขวา” on screen */ $logoTiltDeg = -45; /** filter_var(..., FILTER_VALIDATE_BOOLEAN) returns false for actual booleans — normalize first */ $mirrorInput = $mirror ?? false; $mirror = is_bool($mirrorInput) ? $mirrorInput : filter_var($mirrorInput, FILTER_VALIDATE_BOOLEAN); $intensity = $intensity ?? 'subtle'; $layout = $layout ?? null; $randomizeInput = $randomize ?? true; $randomize = is_bool($randomizeInput) ? $randomizeInput : filter_var($randomizeInput, FILTER_VALIDATE_BOOLEAN); $minEllipses = max(1, min(4, (int) ($minEllipses ?? 1))); $maxEllipses = max(1, min(4, (int) ($maxEllipses ?? 2))); if ($minEllipses > $maxEllipses) { $maxEllipses = $minEllipses; } $effectiveTilt = $mirror ? -$logoTiltDeg : $logoTiltDeg; // Keep size constant even when randomize is enabled (only positions/colors vary). $rx = (int) round(($shapeRxMin + $shapeRxMax) / 2); $ry = (int) max(48, round($rx * $logoRyRef / $logoRxRef)); // Increase subtle opacity slightly so thin strokes don't look “soft/blurred”. $layerFade = $intensity === 'subtle' ? 'opacity-[0.65]' : 'opacity-[0.85]'; /** * Zones in viewBox 0 0 1200 640. * Default: corner layout. 'centered' layout pulls ellipses in closer to the content column (used on products index). */ if ($layout === 'centered') { // Slightly inset from edges, bias around vertical mid so shapes feel near content cards $zones = [ 'tl' => ['cx' => [260, 420], 'cy' => [140, 260]], 'tr' => ['cx' => [780, 940], 'cy' => [140, 260]], 'bl' => ['cx' => [260, 420], 'cy' => [300, 420]], 'br' => ['cx' => [780, 940], 'cy' => [300, 420]], ]; } else { $zones = [ // top-left / top-right 'tl' => ['cx' => [160, 340], 'cy' => [90, 210]], 'tr' => ['cx' => [860, 1000], 'cy' => [90, 210]], // bottom-left / bottom-right 'bl' => ['cx' => [160, 340], 'cy' => [360, 510]], 'br' => ['cx' => [860, 1000], 'cy' => [360, 510]], ]; } if ($randomize) { $n = random_int($minEllipses, $maxEllipses); $cornerKeys = array_keys($zones); // ['tl','tr','bl','br'] // Avoid “stuck together” look by controlling which corners can be paired: // - n=2 => always diagonal pair (TL+BR or TR+BL) // - n=3 => all but one random corner // - n=1 => any single corner // - n=4 => all corners if ($n === 1) { $picked = [$cornerKeys[random_int(0, count($cornerKeys) - 1)]]; } elseif ($n === 2) { $picked = random_int(0, 1) === 0 ? ['tl', 'br'] : ['tr', 'bl']; } elseif ($n === 3) { $exclude = $cornerKeys[random_int(0, count($cornerKeys) - 1)]; $picked = array_values(array_filter($cornerKeys, fn($k) => $k !== $exclude)); } else { // n=4 $picked = $cornerKeys; } // Ensure at least one ellipse stays "on top". // If there is no top-left ("tl"), force top-right ("tr"). $pickedTopKeys = array_values(array_intersect(['tl', 'tr'], $picked)); if (count($pickedTopKeys) === 0) { // Replace one bottom corner with 'tr' to preserve the requested count ($n). $replaceIdx = random_int(0, count($picked) - 1); $picked[$replaceIdx] = 'tr'; } $ellipses = []; foreach ($picked as $key) { $z = $zones[$key]; $ellipses[] = [ 'cx' => random_int($z['cx'][0], $z['cx'][1]), 'cy' => random_int($z['cy'][0], $z['cy'][1]), 'rx' => $rx, 'ry' => $ry, 'deg' => $effectiveTilt, // Keep fill whisper-light; rely on stroke for crisp visibility. 'fillOpacity' => round(random_int(25, 45) / 1000, 3), 'strokeOpacity' => round(random_int(80, 130) / 1000, 3), 'token' => $colorTokens[random_int(0, count($colorTokens) - 1)], ]; } } else { $ellipses = [ [ 'cx' => 220, 'cy' => 130, 'rx' => $rx, 'ry' => $ry, 'deg' => $effectiveTilt, 'fillOpacity' => 0.035, 'strokeOpacity' => 0.095, 'token' => 'primary', ], [ 'cx' => 980, 'cy' => 510, 'rx' => $rx, 'ry' => $ry, 'deg' => $effectiveTilt, 'fillOpacity' => 0.03, 'strokeOpacity' => 0.11, 'token' => 'secondary', ], ]; } if ($randomize) { $gFrom = random_int(3, 6); $gTo = random_int(2, 5); $gradFromToken = $colorTokens[random_int(0, count($colorTokens) - 1)]; $gradToToken = $colorTokens[random_int(0, count($colorTokens) - 1)]; } else { $gFrom = 4; $gTo = 3; $gradFromToken = 'primary'; $gradToToken = 'secondary'; } @endphp